赞
踩
⭐ 简介:大家好,我是zy阿二,是一名对知识充满渴望的自由职业者。
☘️ 最近我沉溺于Python的学习中。你所看到的是我的学习笔记。
❤️ 如果对你有帮助,请关注我,让我们共同进步。有不足之处请留言指正!
Mysql系列文章传送门,建议循序渐进的学习:
1. Mysql入门安装 & Pycharm可视化链接MySQL。入门篇
2. 用Pycharm熟悉MySQL命令,实现增删改查基本操作。基础篇【本文】
注: 本文是入门篇的延续。请先看完入门篇再来看本文!打开Pycharm进入MySQL控制台,跟着一起敲代码!
// 在命令行中几乎所有的sql语句的结尾都需要加上 ; 英文的分号。否则就不会执行。
show databases;
// 不做判断,直接创建,如果test已存在就会报错
create database test;
// 判断如果test不存在,则创建
create database if not exists test;
// 进入文件夹后才可以进一步去创建存放数据的表。
use test;
最终数据是存放在 table 内的, table是在database内的。就相当于目录,一层一层的。
请自行复制后阅读注释。
// 先判断表 tb_name 如果存在,则先删除。 直接删除的命令 drop table tb_name;
// 如果tb_name不存在则会抛出错误 [HY000][1008] Can't drop database 'tb_name'; database doesn't exist
drop table if exists tb_name;
这个SQL语句将创建一个名为tb_name的表,其中包含五个列:
ID列是int整数类型,
name列是varchar(16)
可变长字符串类型,最大不超过16位,如果小于16位那么实际多少位就是多少位,如果超过16位则只保留前16位。
gender列是varchar(16)
可变长字符串类型,
score列是decimal(3, 1)
十进制,有3总位数和1位数,可以存储 -99.9 到 99.9 之间的任何数字,例如 0.0、10.5、-20.3 等
time列是datetime
日期时间类型,例如:2022-02-27 14:30:00
更多数据类型请往后阅读
create table tb_name
(
ID int,
name varchar(16),
gender varchar(16),
score decimal(3, 1),
time datetime
);
每次都需要自己写ID列就太麻烦了,所以把ID列的设为自增型整数 auto_increment primary key (当然你也可以不要ID列,但那是不规范的!不要试图鹤立鸡群 )。在如下示例SQL建表语句是相对比较标准的。
// primary key 设列为主键,必须设置为主键才能设置自增,所以这是必要的
// auto_increment 代表自增型整数,当你插入数据的时候,ID列的内容可以自动递增并写入。
// int 为ID列的数据类型,当你使用sqlite时类型必须是 integer
// 同时主键中的值都是唯一的,不可重复,主键也只能有一列。作用等同于索引index
create table tb_name
(
ID int auto_increment primary key, # 在ID列上直接申明主键
name varchar(16) NOT NULL, # NOT NULL代表不能为空(null)= Python中的None
gender varchar(10) DEFAULT "男", # DEFAULT "男" 代表此列有默认数据为“男”
score decimal(3, 1) COMMENT "成绩", # COMMENT "成绩" 是备注、注释、注解、供自己阅读
time datetime NOT NULL,
UNIQUE (name,ID);
)COMMENT '学生表'; # COMMENT '学生表'这也是是备注、注释、注解、供自己阅读。
UNIQUE (name,ID)
; 这将确保每个name和ID 的组合只能出现一次。例如ID=1,name=张三,已存在。再插入ID=1,name=张三,时就会报错。 但是如果插入ID=2,name=张三,则可以插入。
如果某一列你不希望他出现重复内容,那么就在每列的后面加上 unique
。例如: name varchar(16) NOT NULL unique,
整数类型 | 注释 |
---|---|
TINYINT | 范围是-128到127(使用UNSIGNED修饰符的范围是0到255),存储1字节。 |
SMALLINT | 范围是-32768到32767(使用UNSIGNED修饰符的范围是0到65535),存储2字节。 |
MEDIUMINT | 范围是-8388608到8388607(使用UNSIGNED修饰符的范围是0到16777215),存储3字节。 |
INT | 范围是-2147483648到2147483647(使用UNSIGNED修饰符的范围是0到4294967295),存储4字节。 |
BIGINT | 范围是-9223372036854775808到9223372036854775807(UNSIGNED修饰符范围:0到18446744073709551615),存储8字节。 |
CREATE TABLE my_table (
my_column INT UNSIGNED
);
# 在这个示例中,my_column列定义为INT类型,并使用UNSIGNED修饰符。
# 这意味着它只能存储0到4294967295之间的整数。
# 需要特别注意整数类型的范围,以确保存储的数据不会超出范围
请注意,有些数据库管理系统可能支持其他INT类型,如BITINT、INTEGER等,但上述INT类型是最常用的。此外,一些数据库管理系统允许在INT类型上设置ZEROFILL和UNSIGNED属性,这些属性可以影响INT类型的最大值和最小值。
额外提一下,在SQLite中,使用INTEGER数据类型来定义自增主键列。否则无法正常工作。
在SQLite中即使没有使用AUTOINCREMENT关键字来申明是自增主键,id列将作为ROWID列,SQLite会自动为每个新插入的行分配一个唯一的ROWID值。
ROWID值是一个整数,从1开始递增。例如,以下SQL语句将创建一个包含自增主键列的表:
CREATE TABLE my_table (
id INTEGER PRIMARY KEY,
name varchar(16),
age INTEGER
);
字符串类型 | 注释 |
---|---|
CHAR | 固定长度的字符串,最多可以存储255个字符。如果存储的字符串长度小于指定的长度,则剩余的字符将用空格填充。 |
VARCHAR | 最常用的字符串类型。可变长度的字符串,最多可以存储65535个字符。如果存储的字符串长度小于指定的长度,则不会用空格填充。也可以VARCHAR(255)来指定最大长度。 |
TEXT | 较大的文本数据,最多可以存储65535个字符。 |
MEDIUMTEXT | 更大的文本数据,最多可以存储16777215个字符。 |
LONGTEXT | 非常大的文本数据,最多可以存储4294967295个字符。 |
这也是SQL型数据库的特点(关系型数据)。你必须在写入数据前,预先创建需要多少列和对应的数据格式。在后期严格按照建表的格式进行写入。如果你在后期写入大量数据后想要增加一列,那简直就是一个噩梦。这也是为什么我们还要学习NoSql类(非关系型)数据库的意义。扯远了。。
//方法 1. 指定列名,和要写入的数据一一对应
insert into tb(name,gender,score,dtime) values("张狗蛋",'男',86.5,"2022-12-25 09:08:09");
//方法 2. 不指定列名,有多少列就要写多少条数据,即使ID列是自增型,我们也需要指定 0 或 null
insert into tb values (0, '王麻子', '男', 86.5, '2022-12-25 09:08:09');
insert into tb values (null, '李富贵', '男', 86.5, '2022-12-25 09:08:09');
//方法3. 一次写入多行数据。
insert into tb values (0, '张狗蛋', '男', 50.5, '1989-03-08 23:59:59'),
(0, '王麻子', '男', 66.5, '1990-05-22 16:05:00'),
(0, '赵桂花', '女', 45.5, '1991-08-25 22:15:22'),
(0, '周芬芳', '女', 95.5, '1994-10-10 22:15:22'),
(0, '李富贵', '男', 86.5, '2000-12-20 15:08:19');
附: 使用单引号来包裹字符串类型的数据,用双引号会报错。(当然,也有办法,这里就不展开了。有兴趣的可以去看:MySQL引号的区别)
可视化中我们已经看到写入了很多的数据啦~~
增量即为插入新的数据,跳过已存在的数据。
使用 INSERT INTO
插入数据之前检查表中是否已经存在相同的数据,您可以使用以下 SQL 语句:
INSERT INTO table_name (column1, column2, column3)
SELECT value1, value2, value3
WHERE NOT EXISTS (SELECT 1 FROM table_name WHERE column1 = value1 AND column2 = value2 AND column3 = value3);
上述 SQL 语句的意思是:将值 value1
、value2
和 value3
插入到表 table_name
中的 column1
、column2
和 column3
列中,但是只有当不存在与这些值完全匹配的记录时才进行插入操作。
这里的关键是 WHERE NOT EXISTS
子句,它会检查表中是否存在与新数据匹配的记录。如果存在,该子句将返回false
,然后插入操作将被跳过。如果不存在,该子句将返回 true
,然后插入操作将执行。
以下是一个示例,假设您有一个名为 customers
的表,其中包含 id
、name
和 email
列,现在想要插入新数据,但是只有在表中不存在与新数据完全匹配的记录时才插入数据:
INSERT INTO customers (id, name, email)
SELECT 1, '张三', 'johndoe@163.com'
WHERE NOT EXISTS (SELECT 1 FROM customers WHERE id = 1 AND name = '张三' AND email = 'johndoe@163.com');
但是这种方法在数据库很大的时候,会非常占用资源,所以,如果当你不想要插入重复数据的时候,最好在建表的时候就设置好UNIQUE xxxx;
在插入重复数据遇到UNIQUE 时,程序会报错,所以需要做好报错处理。
如下示例,truncate
清空 customers
表全部数据。无法和where
一起使用,无法回滚rollback,自增列会被初始化,删除速度快。
truncate customers;
如下示例,DELETE
删除customers
表全部数据,可以回滚,自增列不会初始化,会留下日志,删除速度慢。
DELETE FROM customers;
如下示例,ALTER
,重置自增列的当前值为 1
ALTER TABLE customers AUTO_INCREMENT = 1;
DELETE
方法可以带where
子句做条件判断删除。
# 删除 name= '张狗蛋' and gender='男' 的所有行
delete from tb where name= '张狗蛋' and gender='男';
附:where
判断示例 请查看目录: where 条件查询
//查询系统版本
select version();
//计算结果
select 10*2-8 as 结果;
//查询自增列的步长
select @@auto_increment_increment;
// * 代表所有列, tb 代表表的名称
select * from tb;
// 查询tb表中 name 和 score 列的数据
select name,score from tb;
// 别名as , 查询时返回别名。可以给列 和 表 起别名
select name as 姓名,gender as 性别 from tb as 名单;
// 查询tb表中 name 列不重复的数据
select distinct name from tb;
// 查询name, gender两列,合成成一列 姓名性别 返回
select concat(name, gender) as 姓名性别 from tb;
delete
select
update
的后面都可以跟where条件语句。
# 查询score成绩在95~100之间的,返回name和score两列 select name,score from tb where score>=80 and score<=100; # && = and select name,score from tb where score>=80 && score<=100; # 区间查询,score在95~100之间的,返回name和score两列 select name,score from tb where score between 80 and 100; # 返回除了ID=1的其他所有数据 select * from tb where ID != 1; # not = select * from tb where NOT ID = 1; # 查询time字段中包含 99 的数据 select * from tb where time like '%99%'; # 查询time的最后一个字符为 9 的数据 select * from tb where time like '%9'; # 查询time的开头第一个字符是 2 的数据 select * from tb where time like '2%'; # 查询time的倒数第二个字符为 2 的数据 select * from tb where time like '%2_'; # 查询id是1,3,6其中一个并且gender 是女的数据 select * from tb where id in (1, 3, 6) and gender = '女';
update tb set name='平头哥';
如下示例,将 id =1 的name 改为“平头哥” (改所有id=1的,有多少改多少)
update tb set name='平头哥' where id=1;
在原数据基础上做运算后进行修改。如下示例,将 id =1 的score在原基础上+5(改所有id=1的,有多少改多少)
update tb set name='大聪明',score=score+5 where id=1;
如下示例,将 id =2或3 的score在原基础上+5(改所有id=2或3的,有多少改多少)
update tb set name='大聪明',score=score-5 where id=2 or id=3;
如下示例,将 name=‘周芬芳’ 并且 id =4 的gender改为男(因为ID是唯一的,name可能重复)
update tb set gender='男' where name='周芬芳' and id =4;
假设我们有一个名为 users
的表,其中有一个名为 permissions
的整数列,存储了每个用户的权限信息。我们希望将某个用户的权限修改为添加读取数据和修改数据的权限,而不影响其他权限,可以使用位运算符进行更新。
假设该用户的权限是二进制数 0101,其中第 0 位表示读取数据权限,第 1 位表示修改数据权限,其他位为 0。我们要将其更新为 0111,即添加读取数据和修改数据的权限。可以使用位运算符 OR(|)进行更新,代码如下所示:
UPDATE users
SET data = data| 0100
WHERE user_id = 1;
算术运算符:+
(加)、-
(减)、*
(乘)、/
(除)、%
(取余)。
比较运算符:=
(等于)、<>
或 !=
(不等于)、>
(大于)、<
(小于)、>=
(大于等于)、<=
(小于等于)。
逻辑运算符:AND
(和、并且)、OR
(或者)、NOT
(反向、否则、如果不)。
字符串运算符:||(字符串拼接符)、%(通配符)。
位运算符:&
(按位与)、|
(按位或)、^
(按位异或)、~
(按位取反)。
空值运算符:IS NULL
、IS NOT NULL
。
IN
运算符:用于检查某个值是否在给定的一组值之中。
BETWEEN
运算符:用于检查某个值是否在给定的一定范围之内。
# 返回当前时间,格林尼治时间,比北京时间慢8小时 select datetime('now') select date('now') # 只返回日期,没有时分秒 select time('now') # 只返回时分秒,没有日期 # 返回当前时间,本地时间 select datetime('now', 'localtime') select date('now', 'localtime') # 只返回日期,没有时分秒 select time('now', 'localtime') # 只返回时分秒,没有日期 # 返回当前月份最后一天。(加一个月再减1天就是本月最后一天) select datetime('now','start of month','+1 month','-1 day'); # datetime 方法返回日期和时间 # date 方法只返回日期 select date('now','start of month','+1 month','-1 day'); # 返回一年后当前月份的最后一天。(加一年加一个月再减1天就是明年本月的最后一天) select datetime('now','start of month','+1 month','-1 day','+1 year'); # 返回当地时间 减60分钟的时间 select datetime('now','localtime','-60 minute'); # 返回当地时间 加1小时的时间 select datetime('now','localtime','+1 hour'); # 按周计算week方法不可用,返回空值。 select datetime('now','localtime','+1 week'); # 按周计算week方法不可用,返回空值。 # 按周计算week方法不可用,返回空值。 # 计算当前时间和1年前的时间差。 单位“天” select julianday('now') - julianday('now','-1 year'); # 计算当前时间和1天前的时间差。 单位“小时”(天数*24 就是小时啦~) select (julianday('now') - julianday('now','-1 day'))*24; # 计算当前时间和1天前的时间差。 单位“分钟”(天数*24*60 就是分钟啦~) select (julianday('now') - julianday('now','-1 day'))*24*60; # 使用strftime对字符串进行日期data格式化。 select strftime('%Y-%m-%d','2023-01-10'); # 将字符串类型的按指定格式转化成 datetime的格式 select strftime('%Y-%m-%d %H:%M:%S','2023-12-12 12:12:12');
start of year # 代表起始时间为今年
start of month # 代表起始时间为本月
start of week # 代表起始时间为本周
start of day # 代表起始时间为今天
# 示例:
# 查询返回今天的所有数据
SELECT * FROM 表名 WHERE 列名>= datetime('now', 'localtime', 'start of day')
# 查询返回本月的所有数据
SELECT * FROM 表名 WHERE 列名>= datetime('now', 'localtime', 'start of month')
# 查询1440分钟,即24小时内的所有数据
SELECT * FROM 表名 WHERE 列名>= datetime('now','localtime','-1440 minute')
%d 一个月中的第几天 0-31
%f 小数形式的秒 SS.SSSS
%H 小时 00-24
%j 一年中的第几天 01-366
%J Julian Day Number
%m 月份 01-12
%M 分钟 00-59
%s 时间戳,从1970-01-01日开始计算的秒数
%S 秒 00-59
%w 星期 0-6, 0代表星期天
%W 一年中的第几周 00-53
%Y 年份 0000-9999
%%% 百分号
更多SQL命令 | 说明 |
---|---|
set password = password("000000"); | 进入MySQL后输入此命令将密码重置为00000 |
show databases; | 查询MySQL中所有的 database 数据库文件夹 |
create database 数据库名; | 创建一个 database 数据库文件夹 |
drop database 数据库名; | 删除指定 database 数据库文件夹 |
use 数据库名; | 进入 database 数据库文件夹中 |
create table 表名 (列名1 数据类型 属性 注释,列名2 数据类型 属性 注释,列名3 数据类型 属性 注释); | 在当前database创建一个table ,列名 和数据类型为必填参数,属性和注释为可选参数 |
<code>show tables; | 查询当前 database 数据库文件夹下所有的表 |
drop table 表名; | 删除指定 table 表 |
drop table where exists 数据库名; | 删除 指定table 表,如果它存在 |
insert into 表名(列名1,列名2,列名3) values(数据1,数据2,数据3); | 写入数据到 对应的表对应的列 |
truncate 表名; | 清空表中的数据,无法和where一起使用,无法回滚rollback,自增列的值被初始化,删除速度快。 |
delete from 表名; | 删除 表中的数据,可以回滚,自增列的值不会初始化,会留下服务器日志,删除速度慢。 |
delete from 表名 where 条件; | 删除的表中指定条件的数据 |
update 表名 set 列名=数据; | 修改 指定表中指定列的都有数据 |
update 表名 set 列名=数据 where 条件; | 修改 指定表中指定列中满足条件的所有数据 |
update 表名 set 列名=列名+1 where 条件; | 修改 指定表中指定列中满足条件的所有数据在原数据的基础上+1 |
update 表名 set 列名=concat(列名,新数据); | 字符串拼接方法concat,将列名中所有数据 改成 原始数据+新数据。当然也可以加where条件。 |
select * from 表名; | 查询表中的所有数据 |
select 列名,列名,列名 from 表名; | 查询表中指定列名 的数据,一列或多列 |
select 列名 as 新列名 from 表名; | 别名as方法。查询的结果返回 新列名。也可以作用给表名。 |
select 列名,0 as A from tb; | 别名as方法, 查询的结果返回 新增一列A用0填充。只影响返回的结果,不影响原数据。 |
select * from 表名 where 条件; | 查询表中满足条件的数据 |
select 列名1+列名2 as 新列名 from 表名; | 查询表 中两列数据相加的结果返回到新列名中。(数字类型) |
select concat(列名1, " 备注 ", 列名2) as 新列名 from 表名;; | concat方法,字符串拼接。查询返回列名1备注列名2拼接后的数据,并取名新列名 |
+
、 -
、 *
、/
、 >
、 <
、 =
、 !=
、>=
、<=
and
、or
、not
// 查询 id = 1 并且 name = 张三的所有行
select * from tb where id= 1 and name='张狗蛋';
// 查询 id = 1 或者 name = 张三的所有行
select * from tb where id= 2 or name='张狗蛋';
// 查询 id 不等于 1 的所有行
select * from tb where not id= 3 and name = '李富贵';
between ... and ...
区间where 列名 between 最小值 and 最大值;
一般使用在数字类型上。但对于字符数据和日期类型同样可用。
// 查询score 在 50 - 60 之间的货品信息。
select * from tb where score between 50 and 60;
// 查询score 不在 50 - 60 之间的货品信息。
select * from tb where not score between 50 and 60;
//查询englishname 中首字母包含 a - d 的数据
select * from tb where englishname between 'A' and 'D';
// 查询 time 中满足如下时间区间内的数据。
select * from tb where time between '1988-12-01 00:00:00' and '1993-01-01 00:00:00';
in
集合where 列名 in(值1, 值2, ...);
判断数据是否在集合内
// 查询id为 2,3,6,9 的行
select * from tb where id in (2,3,6,9);
// 查询name 不是 王麻子 的行数据
select * from tb where not name in ("王麻子");
// 查询name是 张狗蛋和赵桂花的行数据
select * from tb where name in ("张狗蛋","赵桂花");
is
判断// 查询id 为空的行数据。
select * from tb where score is null;
like '%_%'
模糊匹配like
:模糊查询运算执行通配符;%
表示可有零个或多个任意字符;_
代表需要一个任意字符;// 查询name 列首字是 张的所有行
select * from tb where name like "张%";
// 查询name 列中包含 张的所有行
select * from tb where name like "%张%";
// 查询name 列中倒数第二个字是 张的所有行
select * from tb where name like "%张_";
order by
排序order by 列名。默认升序asc;降序:desc:
// 用 score 升序(小到大),如果score 相同则再按 id 降序(大到小)
select * from tb order by score, age desc;
// 用 score 降序(大到小)
select * from tb order by score desc;
limit
限制和忽略// 查询是限制返回的最大行数为3。即查询前3行
select * from tb limit 3;
// 查询从第4行开始,查询前3行
select * from tb limit 3;4
语句 | 注释 |
---|---|
count(*) | 统计最大行数 |
sum(列) | 取列的总和 |
max(列) | 取列的最大值 |
min(列) | 取列的最小值 |
avg(列) | 取列的平均值 |
// 查询id列共有多少数据 select count(id) from tb; // 查询所有列有多少条数据 select count(*) from tb; // 查询score列的总和 select sum(score) from tb; // 查询score列和 score2列 两列的总和 select sum(score,score2) from tb; // 查询score的平均值 select avg(score) from tb; // 查询score 不等于100 和 不等于1 的平均值 select avg(score) from tb where score != 100 and score != 1 select avg(score) from tb where score not in(100,1) // 查询score 去掉最大值和最小值后取平均值 select avg(score) from tb where score not in ((select max(score) from tb, (select min(score) from tb));
命令 | 作用 |
---|---|
abs(-1); | 取绝对值 |
rand(); | 返回 0-1区间的随机数 |
rand()*100; | 返回1-100区间的随机数。 |
power(x,y); | 返回x的y次方 |
round(x); | 返回离x最近的整数,四舍五入(只看小数点第一位) |
round(x,y); | 保留x的y位小数点四舍五入 |
sqrt(x); | 返回x的平方根 |
truncate(x,y); | 返回数字x,保留y位小数。(多余位数直接删掉) |
ceil(x); | 返回 >=x的最小整数(向上取整) |
floor(x); | 返回 >=x的最小整数(向下取整) |
greatest(x,y,z) | 返回集合xyz中的最大值 |
least(x,y,z) | 返回集合xyz中的最小值,有 null 返回 null |
ceil(rand()*100); | 返回1-100的随机整数。解:先取1~100的随机数再向上取整。 |
mod(ceil(rand()*100),6); | 随机生成0-5的随机数。解:先取1~100的随机整数再用6整除后取余 |
上表命令都要开头加 select 。 示例:
# 随机生成0-5的随机数。解:先取1~100的随机整数再用6整除后取余
select mod(ceil(rand()*100),6);
命令 | 作用 |
---|---|
length(x); | 返回字符串x的长度 |
trim(); | 返回去除指定字符的值(详见下方示例代码) |
concat(x,y); | 字符串拼接,把x、y拼接成一个字符串 |
upper(x); | 将x 的所有字符串变成大写 |
lower(x); | 将x 的所有字符串变成小写 |
left(x,y); | 返回字符串x的前y个字符 |
right(x,y); | 返回字符串x的后y个字符 |
repeat(x,y); | 将字符串x重复y次 |
space(x); | 返回空格,x个 |
replace(x,y,z); | 将x字符串中的y替换成z |
strcmp(x,y); | 比较x和y,返回的值可以为-1,0,1 |
substring(x,y,z); | 获取从字符串x中的第y个位置开始长度为z的字符串 |
reverse(x); | 将字符串x反转,左右顺序交换 |
select trim(' 123123 '); # 删除所有空格 返回:(123123)
select ltrim(' 123123 '); # 删除左边空格 返回:(123123 )
select rtrim(' 123123 '); # 删除右边空格 返回:( 123123)
select trim(both '1' from '1112111'); #删除所有 1 返回:(2)
select trim(leading '1' from '1112111'); #删除左边所有 1 返回:(2111)
select trim(trailing '1' from '1112111'); #删除右边边所有 1 返回:(1112)
select replace('xyyy','y','z') # 将xyyy里的y替换成z。 返回:(xzzz)
select reverse('123456789') # 将123456789的顺序颠倒。返回:(987654321)
MySQL支持日期时间处理,提供了很多处理日期和时间的函数。
命令 | 作用 |
---|---|
now(); | 返回当前年月日 时分秒 |
curdate(); | 返回当前年月日 |
curtime(); | 返回当前时分秒 |
year(now());; | 返回当前的 年 |
month(now());; | 返回当前的 月 |
day(now());; | 返回当前的 日 |
week(now()); | 返回当前是今年的第几个周 |
hour(now()); | 返回当前的 时 |
minute(now()); | 返回当前的 分 |
second(now()); | 返回当前的 秒 |
dayofweek(now()); | 返回当前是这周的第几天,1=周日,2=周一,3=周二,4=周三 |
dayofyear(now()); | 返回今年过了多少天 |
group by
列相同数据分组# 先看下group by语法结构
select 列A from 表 group by 列A;
group by语法可以根据给定的数据列的每个成员对查询结果进行分组统计,最终得到一个分组汇总表。select子句中的列名必须为分组列或列函数。列函数对于group by子句定义的每个组各返回一个结果。看不懂。。好深奥?
重新解释:示例1:
# 要求:分别统计男女人数。
insert into tb(name,gender,age,score,class)
values ('张狗蛋', '男', 10, 67, '一班'),
('王麻子', '男', 11, 76, '一班'),
('赵桂花', '女', 10, 89, '一班'),
('周芬芳', '女', 10, 95, '一班'),
('周刘海', '女', 10, 90, '二班'),
('孙美丽', '女', 10, 88, '二班'),
('李富贵', '男', 11.5, 92, '二班');
# 解题思路:首先通过 select gender,我们需要展示的数据
# 然后,再用count方法统计数量,然后查询的表为from tb
# 最后加上子句 group by gender,根据gender分组。因为gender只有男、女所以就会被分成2组
select gender,count(gender) from tb group by gender;
示例2:
# 还是这份数据。要求根据班级分组,计算出每个班的平均分
insert into tb(name,gender,age,score,class)
values ('张狗蛋', '男', 10, 67, '一班'),
('王麻子', '男', 11, 76, '一班'),
('赵桂花', '女', 10, 89, '一班'),
('周芬芳', '女', 10, 95, '一班'),
('周刘海', '女', 10, 90, '二班'),
('孙美丽', '女', 10, 88, '二班'),
('李富贵', '男', 11.5, 92, '二班');
# 解题思路:首先定位分组列select class,
# 然后统计我们要的平均分avg(score)
# 加form tb 加子句 group by class;
select class,avg(score) from tb group by class;
group by ... having
分组查询过滤group by子句之后使用having子句。可应用限定条件进行分组,以便系统仅对满足条件的组返回结果。having类似于where(唯一的差别是where过滤行,having过滤组)haveing支持所有where操作符。
还是用示例说话,示例1:
# 还是这份数据。 insert into tb(name,gender,age,score,class) values ('张狗蛋', '男', 10, 67, '一班'), ('王麻子', '男', 11, 76, '一班'), ('赵桂花', '女', 10, 89, '一班'), ('周芬芳', '女', 10, 95, '一班'), ('周刘海', '女', 10, 90, '二班'), ('孙美丽', '女', 10, 88, '二班'), ('李富贵', '男', 11, 92, '二班'), ('汪达达', '男', 45, 92, '二班'), ('王溜子', '男', 18, 88, '二班'), ('马大哈', '男', 19, 95, '三班'), ('任我行', '男', 55, 90, '三班'), ('任盈盈', '女', 18, 98, '三班'), ('令狐冲', '男', 24, 99, '三班'); # 还是按班级分组计算平均分。但是只需要二班和三班的。排错一班。 select class,avg(score) from tb group by class having class != '一班' # 加大难度,我们现在需要分别得到三个班级中,男女的数量,并且数量为1的数据 select class, gender, count(gender) from tb group by class, gender having count(gender) != 1;
SELECT 列名A,count(列名A) as 重复次数 # 设置需要返回的列和要统计有重复内容的列
FROM 表名A # 要查询的表名
WHERE ID > 0 # 设置筛选的条件,ID大于0的内容
GROUP BY 列名A # 用列名A分组达到去重显示的目的
HAVING count(列名A) > 1 # 返回 列名A 中重复的次数大于1次的
ORDER BY 出现次数 DESC # 根据重复次数从大到小排序。 从小到大ASC
存储引擎 | 优势 | 劣势 | 适用场景 |
---|---|---|---|
ISAM | 快速读取,不占用大量的内存和存储资源 | 不支持事务、外来键、索引。硬盘崩溃数据无法恢复 | |
MYIAM | 快速读取 | 不支持事务 | 很多count计算;插入不频繁,查询频繁 |
HEAP | 极高的插入、更新和查询效率,默认使用哈希索引 | 数据存储在内存中的临时表格,保存的数据具有不稳定性 | 临时存储需要的表 |
INNODB | 有提交、回滚和奔溃恢复能力的饰物安全存储引擎 | 读取速度比ISAM慢 | 数据更新、查询都相当频繁,且表锁定的计划较大的情况 |
ARCHIVE | 有高效的插入速度 | 不支持索引,仅支持insert和select语句 | 存储大量独立的,作为历史记录的数据,如日志,聚合分析 |
默认引擎:
静态MyISAM:如果数据库中的各个数据列的长度都是预先固定好的,服务器将自动选择这种表类型。(1)表中每一条记录所占用的空间都是一样的,所以存取和更新的效率非常高。(2)当数据受损时,回复工作也比较容易做。
动态MyISAM:如果数据表中出现varchar、xxxtex或xxxBLOB字段时,服务器将自动选择这种表类型。相对于静态MyISAM,这种表存储空间比较小。
END
还有很多知识点如:外键,联合多表查询、自连接、合并查询、内连接、左连接、右链接、子查询 等。有兴趣的猿人可以继续深造。。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。