赞
踩
需要云服务器等云产品来学习Linux的同学可以移步/-->腾讯云<--/-->阿里云<--/-->华为云<--/官网,轻量型云服务器低至112元/年,新用户首次下单享超低折扣。
目录
2.4数学成绩是 58 或者 59 或者 98 或者 99 分的同学及数学成绩
2.9孙某同学,否则要求总成绩 > 200 并且 语文成绩 < 数学成绩 并且 英语成绩 > 80
3、order by asc/desc(对结果进行升序/降序)
3.2查询同学各门成绩,依次按 数学降序,英语降序,语文升序的方式显示
3.4查询姓孙的同学或者姓曹的同学数学成绩,结果按数学成绩由高到低显示
2、将曹孟德的数学成绩变更为 60 分,语文成绩变更为 70 分
五、将筛选出来的数据插入到数据库中(insert+select)
1、COUNT([DISTINCT] expr) 返回查询到的数据的数量
2、SUM([DISTINCT] expr) 返回查询到的数据的 总和,不是数字没有意义
3、AVG([DISTINCT] expr) 返回查询到的数据的 平均值,不是数字没有意义
4、MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义
5、MIN([DISTINCT] expr)返回查询到的数据的 最小值,不是数字没有意义
5、‘史密斯’不参与统计,显示每个部门、每种岗位的平均工资低于2000的工种
CRUD : Create(创建), Retrieve(读取),Update(更新),Delete(删除)
语法:
- INSERT [INTO] table_name
- [(column [, column] ...)]
- VALUES (value_list) [, (value_list)] ...
- value_list: value, [, value] ...
先创建一张学生表:
- --创建学生表
- mysql> create table if not exists students(
- -> id int unsigned primary key auto_increment,
- -> sn int unsigned unique key,
- -> name varchar(20) not null,
- -> qq varchar(32) unique key
- -> );
- Query OK, 0 rows affected (0.31 sec)
指定列单行插入:
- mysql> insert into students (sn,name,qq) values (100,'张三','123456');
- Query OK, 1 row affected (0.04 sec)
单行全列插入:
- mysql> insert into students values (2,101,'李四','222222');
- Query OK, 1 row affected (0.05 sec)
- mysql> insert into students (sn,name,qq) values (102,'王五','333333'),(103,'赵六',444444);
- Query OK, 2 rows affected (0.04 sec)
- Records: 2 Duplicates: 0 Warnings: 0
插入的每条数据逗号隔开,达到一次插入多行的效果。
- --打印当前学生表数据
- mysql> select* from students;
- +----+------+--------+--------+
- | id | sn | name | qq |
- +----+------+--------+--------+
- | 1 | 100 | 张三 | 123456 |
- | 2 | 101 | 李四 | 222222 |
- | 3 | 102 | 王五 | 333333 |
- | 4 | 103 | 赵六 | 444444 |
- +----+------+--------+--------+
- 4 rows in set (0.00 sec)
- --重复插入主键为2的值,主键冲突,插入失败
- mysql> insert into students values (2,104,'小明','111111');
- ERROR 1062 (23000): Duplicate entry '2' for key 'PRIMARY'
- --插入变更新,注意作为更新的值可以和插入的值不一样
- mysql> insert into students values (2,104,'小明',111111) on duplicate key update sn=104,name='小明',qq='111111';
- Query OK, 2 rows affected (0.04 sec)
- --打印当前学生表数据,发现id=2的数据被更新
- mysql> select* from students;
- +----+------+--------+--------+
- | id | sn | name | qq |
- +----+------+--------+--------+
- | 1 | 100 | 张三 | 123456 |
- | 2 | 104 | 小明 | 111111 |
- | 3 | 102 | 王五 | 333333 |
- | 4 | 103 | 赵六 | 444444 |
- +----+------+--------+--------+
- 4 rows in set (0.01 sec)
对数据进行插入,首先数据要合法(相关字段没有被唯一键、主键、外键等进行约束),其次如果插入数据的id已存在,将会更新sn、name和qq而不是插入失败。
- --如果替代的数据在表中无冲突,replace将被当成插入
- mysql> replace into students (sn,name,qq) values (105,'小红','555555');
- Query OK, 1 row affected (0.46 sec)
- --打印当前学生表数据,可以看到表中多了一行小红的信息
- mysql> select* from students;
- +----+------+--------+--------+
- | id | sn | name | qq |
- +----+------+--------+--------+
- | 1 | 100 | 张三 | 123456 |
- | 2 | 104 | 小明 | 111111 |
- | 3 | 102 | 王五 | 333333 |
- | 4 | 103 | 赵六 | 444444 |
- | 5 | 105 | 小红 | 555555 |
- +----+------+--------+--------+
- 5 rows in set (0.00 sec)
- --再次replace,唯一键存在冲突,小红1的数据将替换小红的数据
- mysql> replace into students (sn,name,qq) values (105,'小红1','555555');
- Query OK, 2 rows affected (0.02 sec)
- --打印当前学生表数据,发现小红1的id变为6
- mysql> select* from students;
- +----+------+---------+--------+
- | id | sn | name | qq |
- +----+------+---------+--------+
- | 1 | 100 | 张三 | 123456 |
- | 2 | 104 | 小明 | 111111 |
- | 3 | 102 | 王五 | 333333 |
- | 4 | 103 | 赵六 | 444444 |
- | 6 | 105 | 小红1 | 555555 |
- +----+------+---------+--------+
- 5 rows in set (0.00 sec)
主键 或者 唯一键 没有冲突,则直接插入;
主键 或者 唯一键 如果冲突,则删除后再插入。
有个细节:当发生替换时,因为主键会自增长并且replace是删除后再替换,所以用于替换的行id将会使用下一个自增的id。如上面的SQL语句中,原先小红的id是5,被替换成小红1后,id变为6。
语法:
- SELECT
- [DISTINCT] {* | {column [, column] ...}
- [FROM table_name]
- [WHERE ...]
- [ORDER BY column [ASC | DESC], ...]
- LIMIT ...
先创建一张成绩表:
- --创建成绩表
- mysql> CREATE TABLE exam_result (
- -> id INT UNSIGNED PRIMARY KEY AUTO_INCREMENT,
- -> name VARCHAR(20) NOT NULL COMMENT '同学姓名',
- -> chinese float DEFAULT 0.0 COMMENT '语文成绩',
- -> math float DEFAULT 0.0 COMMENT '数学成绩',
- -> english float DEFAULT 0.0 COMMENT '英语成绩'
- -> );
- Query OK, 0 rows affected (0.14 sec)
- --插入测试数据
- mysql> INSERT INTO exam_result (name, chinese, math, english) VALUES
- -> ('A', 67, 98, 56),
- -> ('B', 87, 78, 77),
- -> ('C', 88, 98, 90),
- -> ('D', 82, 84, 67),
- -> ('E', 55, 85, 45),
- -> ('F', 70, 73, 78),
- -> ('G', 75, 65, 30);
- ds: 7 Duplicates: 0 Warnings: 0Query OK, 7 rows affected (0.03 sec)
- Records: 7 Duplicates: 0 Warnings: 0
- mysql> select* from exam_result;
- +----+------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+------+---------+------+---------+
- | 1 | A | 67 | 98 | 56 |
- | 2 | B | 87 | 78 | 77 |
- | 3 | C | 88 | 98 | 90 |
- | 4 | D | 82 | 84 | 67 |
- | 5 | E | 55 | 85 | 45 |
- | 6 | F | 70 | 73 | 78 |
- | 7 | G | 75 | 65 | 30 |
- +----+------+---------+------+---------+
- 7 rows in set (0.00 sec)
通常情况下不建议使用 * 进行全列查询
1. 查询的列越多,意味着需要传输的数据量越大;
2. 可能会影响到索引的使用。
- --指定姓名和数学成绩列进行查询
- mysql> select name,math from exam_result;
- +------+------+
- | name | math |
- +------+------+
- | A | 98 |
- | B | 78 |
- | C | 98 |
- | D | 84 |
- | E | 85 |
- | F | 73 |
- | G | 65 |
- +------+------+
- 7 rows in set (0.00 sec)
- --利用selsct计算平均分
- mysql> select name,math,(chinese+math+english)/3 from exam_result;
- +------+------+--------------------------+
- | name | math | (chinese+math+english)/3 |
- +------+------+--------------------------+
- | A | 98 | 73.66666666666667 |
- | B | 78 | 80.66666666666667 |
- | C | 98 | 92 |
- | D | 84 | 77.66666666666667 |
- | E | 85 | 61.666666666666664 |
- | F | 73 | 73.66666666666667 |
- | G | 65 | 56.666666666666664 |
- +------+------+--------------------------+
-
- --觉得计算式太长,可以用as给它重命名为average
- mysql> select name,math,(chinese+math+english)/3 as average from exam_result;
- +------+------+--------------------+
- | name | math | average |
- +------+------+--------------------+
- | A | 98 | 73.66666666666667 |
- | B | 78 | 80.66666666666667 |
- | C | 98 | 92 |
- | D | 84 | 77.66666666666667 |
- | E | 85 | 61.666666666666664 |
- | F | 73 | 73.66666666666667 |
- | G | 65 | 56.666666666666664 |
- +------+------+--------------------+
- 7 rows in set (0.02 sec)
-
- --当然这个as可以省略
- mysql> select name 姓名,math 数学,(chinese+math+english)/3 平均分 from exam_result;
- +--------+--------+--------------------+
- | 姓名 | 数学 | 平均分 |
- +--------+--------+--------------------+
- | A | 98 | 73.66666666666667 |
- | B | 78 | 80.66666666666667 |
- | C | 98 | 92 |
- | D | 84 | 77.66666666666667 |
- | E | 85 | 61.666666666666664 |
- | F | 73 | 73.66666666666667 |
- | G | 65 | 56.666666666666664 |
- +--------+--------+--------------------+
- 7 rows in set (0.01 sec)
- mysql> select distinct math from exam_result;
- +------+
- | math |
- +------+
- | 98 |
- | 78 |
- | 84 |
- | 85 |
- | 73 |
- | 65 |
- +------+
- 6 rows in set (0.00 sec)
比较运算符:
运算符 | 说明 |
>, >=, <, <= | 大于,大于等于,小于,小于等于 |
= | 等于,NULL 不安全,例如 NULL = NULL 的结果是 NULL |
<=> | 等于,NULL 安全,例如 NULL <=> NULL 的结果是 TRUE(1) |
!=, <> | 不等于(这两个符号都是NULL不安全的) |
BETWEEN a0 AND a1 | 范围匹配,[a0, a1],如果 a0 <= value <= a1,返回 TRUE(1) |
IN (option, ...) | 如果是 option 中的任意一个,返回 TRUE(1) |
IS NULL | 是 NULL |
IS NOT NULL | 不是 NULL |
LIKE | 模糊匹配。like 'A%'。% 表示任意多个(包括 0 个)任意字符;like 'A_'。_ 表示任意一个字符 |
逻辑运算符:
运算符 | 说明 |
AND | 多个条件必须都为 TRUE(1),结果才是 TRUE(1) |
OR | 任意一个条件为 TRUE(1), 结果为 TRUE(1) |
NOT | 条件为 TRUE(1),结果为 FALSE(0) |
- mysql> select name,english from exam_result where english<60;
- +------+---------+
- | name | english |
- +------+---------+
- | A | 56 |
- | E | 45 |
- | G | 30 |
- +------+---------+
- 3 rows in set (0.00 sec)
- -- >=和<=
- mysql> select name,chinese from exam_result where chinese>=80 and chinese <=90;
- +------+---------+
- | name | chinese |
- +------+---------+
- | B | 87 |
- | C | 88 |
- | D | 82 |
- +------+---------+
- 3 rows in set (0.01 sec)
-
- --between a0 and a1
- mysql> select name,chinese from exam_result where chinese between 80 and 90;
- +------+---------+
- | name | chinese |
- +------+---------+
- | B | 87 |
- | C | 88 |
- | D | 82 |
- +------+---------+
- 3 rows in set (0.00 sec)
- --可以采用多个or
- mysql> select name,math from exam_result where math=58 or math=59 or math=98 or math=99;
- +------+------+
- | name | math |
- +------+------+
- | A | 98 |
- | C | 98 |
- +------+------+
- 2 rows in set (0.02 sec)
-
- --可以用in(......)
- mysql> select name,math from exam_result where math in(58,59,98,99);
- +------+------+
- | name | math |
- +------+------+
- | A | 98 |
- | C | 98 |
- +------+------+
- 2 rows in set (0.00 sec)
- --对新表插入数据
- INSERT INTO exam_result (name, chinese, math, english) VALUES
- ('唐三藏', 67, 98, 56),
- ('孙悟空', 87, 78, 77),
- ('猪悟能', 88, 98, 90),
- ('曹孟德', 82, 84, 67),
- ('刘玄德', 55, 85, 45),
- ('孙权', 70, 73, 78),
- ('宋公明', 75, 65, 30);
- -- like '孙%'找到所有孙姓同学,%代表后面模糊匹配0-n个字符
- mysql> select name from exam_result where name like '孙%';
- +-----------+
- | name |
- +-----------+
- | 孙悟空 |
- | 孙权 |
- +-----------+
- 2 rows in set (0.00 sec)
-
- --like '孙_'找到所有孙某同学,_代表模糊匹配1个字符
- mysql> select name from exam_result where name like '孙_';
- +--------+
- | name |
- +--------+
- | 孙权 |
- +--------+
- 1 row in set (0.00 sec)
- mysql> select name,chinese,english from exam_result where chinese>english;
- +-----------+---------+---------+
- | name | chinese | english |
- +-----------+---------+---------+
- | 唐三藏 | 67 | 56 |
- | 孙悟空 | 87 | 77 |
- | 曹孟德 | 82 | 67 |
- | 刘玄德 | 55 | 45 |
- | 宋公明 | 75 | 30 |
- +-----------+---------+---------+
- 5 rows in set (0.00 sec)
- mysql> select name,chinese,math,english,chinese+math+english 总分 from exam_result where chinese+math+english<200;
- +-----------+---------+------+---------+--------+
- | name | chinese | math | english | 总分 |
- +-----------+---------+------+---------+--------+
- | 刘玄德 | 55 | 85 | 45 | 185 |
- | 宋公明 | 75 | 65 | 30 | 170 |
- +-----------+---------+------+---------+--------+
- 2 rows in set (0.00 sec)
该SQL的执行顺序如上图所示。所以where后面直接用总分来表示chinese+math+english是不行的。(去exam_result表里找chinese+math+english小于200的同学进行打印)
- mysql> select name,chinese from exam_result where chinese>80 and name not like '孙%';
- +-----------+---------+
- | name | chinese |
- +-----------+---------+
- | 猪悟能 | 88 |
- | 曹孟德 | 82 |
- +-----------+---------+
- 2 rows in set (0.00 sec)
- mysql> select name,chinese,math,english,chinese+math+english 总分 from exam_result where name like '孙_' or (chinese+math+english>200 and chinese<math and english>80);
- +-----------+---------+------+---------+--------+
- | name | chinese | math | english | 总分 |
- +-----------+---------+------+---------+--------+
- | 猪悟能 | 88 | 98 | 90 | 276 |
- | 孙权 | 70 | 73 | 78 | 221 |
- +-----------+---------+------+---------+--------+
- 2 rows in set (0.00 sec)
- --创建一个新表
- mysql> create table test(
- -> id int,
- -> name varchar(20)
- -> );
- Query OK, 0 rows affected (0.09 sec)
-
- --插入数据
- mysql> insert into test (id,name) values (1,'张三');
- Query OK, 1 row affected (0.04 sec)
- mysql> insert into test (id,name) values (null,'张三');
- Query OK, 1 row affected (0.05 sec)
- mysql> insert into test (id,name) values (1,null);
- Query OK, 1 row affected (0.05 sec)
- mysql> insert into test (id,name) values (null,null);
- Query OK, 1 row affected (0.02 sec)
- mysql> insert into test (id,name) values (1,'');
- Query OK, 1 row affected (0.01 sec)
- --打印表结构
- mysql> select* from test;
- +------+--------+
- | id | name |
- +------+--------+
- | 1 | 张三 |
- | NULL | 张三 |
- | 1 | NULL |
- | NULL | NULL |
- | 1 | |
- +------+--------+
- 5 rows in set (0.02 sec)
null的查询:
- mysql> select* from test where name is null;
- +------+------+
- | id | name |
- +------+------+
- | 1 | NULL |
- | NULL | NULL |
- +------+------+
- 2 rows in set (0.01 sec)
-
- mysql> select* from test where name is not null;
- +------+--------+
- | id | name |
- +------+--------+
- | 1 | 张三 |
- | NULL | 张三 |
- | 1 | |
- +------+--------+
- 3 rows in set (0.01 sec)
注意:null是null,空串是空串,不一样。
- mysql> SELECT NULL = NULL, NULL = 1, NULL = 0;
- +-------------+----------+----------+
- | NULL = NULL | NULL = 1 | NULL = 0 |
- +-------------+----------+----------+
- | NULL | NULL | NULL |
- +-------------+----------+----------+
- 1 row in set (0.00 sec)
-
- mysql> SELECT NULL <=> NULL, NULL <=> 1, NULL <=> 0;
- +---------------+------------+------------+
- | NULL <=> NULL | NULL <=> 1 | NULL <=> 0 |
- +---------------+------------+------------+
- | 1 | 0 | 0 |
- +---------------+------------+------------+
- 1 row in set (0.01 sec)
null之间的比较不能用=,得用<=>或者is null或者is not null
- mysql> select name,math from exam_result order by math asc;
- +-----------+------+
- | name | math |
- +-----------+------+
- | 张三 | NULL |
- | 宋公明 | 65 |
- | 孙权 | 73 |
- | 孙悟空 | 78 |
- | 曹孟德 | 84 |
- | 刘玄德 | 85 |
- | 唐三藏 | 98 |
- | 猪悟能 | 98 |
- +-----------+------+
- 8 rows in set (0.00 sec)
-
- mysql> select name,math from exam_result order by math desc;
- +-----------+------+
- | name | math |
- +-----------+------+
- | 唐三藏 | 98 |
- | 猪悟能 | 98 |
- | 刘玄德 | 85 |
- | 曹孟德 | 84 |
- | 孙悟空 | 78 |
- | 孙权 | 73 |
- | 宋公明 | 65 |
- | 张三 | NULL |
- +-----------+------+
- 8 rows in set (0.00 sec)
-- ASC 为升序(从小到大)
-- DESC 为降序(从大到小)
-- 默认为 ASC
-- NULL 视为比任何值都小
- mysql> select name,math,english,chinese from exam_result order by math desc,english desc,chinese asc;
- +-----------+------+---------+---------+
- | name | math | english | chinese |
- +-----------+------+---------+---------+
- | 猪悟能 | 98 | 90 | 88 |
- | 唐三藏 | 98 | 56 | 67 |
- | 刘玄德 | 85 | 45 | 55 |
- | 曹孟德 | 84 | 67 | 82 |
- | 孙悟空 | 78 | 77 | 87 |
- | 孙权 | 73 | 78 | 70 |
- | 宋公明 | 65 | 30 | 75 |
- | 张三 | NULL | NULL | NULL |
- +-----------+------+---------+---------+
- 8 rows in set (0.00 sec)
- mysql> select name,chinese,math,english,chinese+math+english 总分 from exam_result order by 总分 desc;
- +-----------+---------+------+---------+--------+
- | name | chinese | math | english | 总分 |
- +-----------+---------+------+---------+--------+
- | 猪悟能 | 88 | 98 | 90 | 276 |
- | 孙悟空 | 87 | 78 | 77 | 242 |
- | 曹孟德 | 82 | 84 | 67 | 233 |
- | 唐三藏 | 67 | 98 | 56 | 221 |
- | 孙权 | 70 | 73 | 78 | 221 |
- | 刘玄德 | 55 | 85 | 45 | 185 |
- | 宋公明 | 75 | 65 | 30 | 170 |
- | 张三 | NULL | NULL | NULL | NULL |
- +-----------+---------+------+---------+--------+
- 8 rows in set (0.00 sec)
-
- mysql>
上面的where语句是不能用别名的。但在这里可以使用别名,还是因为顺序的问题。
第一优先级:明确找的是哪张表exam_result
第二优先级:where子句
第三优先级:chinese+math+english 总分
第四优先级:order by 总分 desc(要有合适的数据再进行排序)
第五优先级:limit(数据准备好了,才进行显示)
- mysql> select name,math from exam_result where name like '孙%' or name like '曹%' order by math desc limit 3 offset 0;
- +-----------+------+
- | name | math |
- +-----------+------+
- | 曹孟德 | 84 |
- | 孙悟空 | 78 |
- | 孙权 | 73 |
- +-----------+------+
- 3 rows in set (0.00 sec)
- --从表开始连续读取5行
- mysql> select* from exam_result limit 5;
- +----+-----------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+-----------+---------+------+---------+
- | 1 | 唐三藏 | 67 | 98 | 56 |
- | 2 | 孙悟空 | 87 | 78 | 77 |
- | 3 | 猪悟能 | 88 | 98 | 90 |
- | 4 | 曹孟德 | 82 | 84 | 67 |
- | 5 | 刘玄德 | 55 | 85 | 45 |
- +----+-----------+---------+------+---------+
- 5 rows in set (0.01 sec)
-
- --limit 1,3;开始位置1是下标,3是步长
- mysql> select* from exam_result limit 1,3;
- +----+-----------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+-----------+---------+------+---------+
- | 2 | 孙悟空 | 87 | 78 | 77 |
- | 3 | 猪悟能 | 88 | 98 | 90 |
- | 4 | 曹孟德 | 82 | 84 | 67 |
- +----+-----------+---------+------+---------+
- 3 rows in set (0.01 sec)
-
- --limit s offset n其中s代表步长,n代表下标
- mysql> select* from exam_result limit 3 offset 5;
- +----+-----------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+-----------+---------+------+---------+
- | 6 | 孙权 | 70 | 73 | 78 |
- | 7 | 宋公明 | 75 | 65 | 30 |
- | 8 | 张三 | NULL | NULL | NULL |
- +----+-----------+---------+------+---------+
- 3 rows in set (0.00 sec)
对未知表进行查询时,最好加一条 LIMIT 1,避免因为表中数据过大,查询全表数据导致数据库卡死。
select* from exam_result limit 0,3;
select* from exam_result limit 3,3;
select* from exam_result limit 6,3;
......
select* from exam_result limit 3 offset 0;
select* from exam_result limit 3 offset 3;
select* from exam_result limit 3 offset 6;
进行分页展示。
语法:
- UPDATE table_name SET column = expr [, column = expr ...]
- [WHERE ...] [ORDER BY ...] [LIMIT ...]
- mysql> update exam_result set math=80 where name ='孙悟空';
- Query OK, 1 row affected (0.07 sec)
- mysql> update exam_result set math=60,chinese=70 where name ='曹孟德';
- Query OK, 1 row affected (0.01 sec)
- Rows matched: 1 Changed: 1 Warnings: 0
- mysql> update exam_result set math=math+30 order by chinese+math+english asc limit 3;
- Query OK, 2 rows affected (0.05 sec)
- Rows matched: 3 Changed: 2 Warnings: 0
- mysql> update exam_result set chinese=chinese*2;
- Query OK, 7 rows affected (0.04 sec)
- Rows matched: 8 Changed: 7 Warnings: 0
-
- mysql> select * from exam_result;
- +----+-----------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+-----------+---------+------+---------+
- | 1 | 唐三藏 | 134 | 98 | 56 |
- | 2 | 孙悟空 | 174 | 80 | 77 |
- | 3 | 猪悟能 | 176 | 98 | 90 |
- | 4 | 曹孟德 | 140 | 60 | 67 |
- | 5 | 刘玄德 | 110 | 115 | 45 |
- | 6 | 孙权 | 140 | 73 | 78 |
- | 7 | 宋公明 | 150 | 95 | 30 |
- | 8 | 张三 | NULL | NULL | NULL |
- +----+-----------+---------+------+---------+
- 8 rows in set (0.00 sec)
没有where子句直接更新全表,需谨慎!update的搞错了危害不亚于delete。
语法:
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]
- mysql> delete from exam_result where name='孙悟空';
- Query OK, 1 row affected (0.04 sec)
-
- mysql> select * from exam_result;
- +----+-----------+---------+------+---------+
- | id | name | chinese | math | english |
- +----+-----------+---------+------+---------+
- | 1 | 唐三藏 | 134 | 98 | 56 |
- | 3 | 猪悟能 | 176 | 98 | 90 |
- | 4 | 曹孟德 | 140 | 60 | 67 |
- | 5 | 刘玄德 | 110 | 115 | 45 |
- | 6 | 孙权 | 140 | 73 | 78 |
- | 7 | 宋公明 | 150 | 95 | 30 |
- | 8 | 张三 | NULL | NULL | NULL |
- +----+-----------+---------+------+---------+
- 7 rows in set (0.00 sec)
- mysql> delete from exam_result order by chinese+math+english desc limit 1;
- Query OK, 1 row affected (0.02 sec)
- --准备测试表
- mysql> CREATE TABLE for_delete (
- -> id INT PRIMARY KEY AUTO_INCREMENT,
- -> name VARCHAR(20)
- -> );
- Query OK, 0 rows affected (0.15 sec)
- --插入测试数据
- mysql> INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
- Query OK, 3 rows affected (0.04 sec)
- Records: 3 Duplicates: 0 Warnings: 0
- --查看表结构
- mysql> select* from for_delete;
- +----+------+
- | id | name |
- +----+------+
- | 1 | A |
- | 2 | B |
- | 3 | C |
- +----+------+
- 3 rows in set (0.00 sec)
- --查看创建表时的SQL,可以发现,下一次自增的id值是4
- mysql> show create table for_delete\G;
- *************************** 1. row ***************************
- Table: for_delete
- Create Table: CREATE TABLE `for_delete` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=gbk
- 1 row in set (0.00 sec)
- --删除表
- mysql> delete from for_delete;
- Query OK, 3 rows affected (0.04 sec)
- --查看创建表的SQL,发现自增值仍为4
- mysql> show create table for_delete\G;
- *************************** 1. row ***************************
- Table: for_delete
- Create Table: CREATE TABLE `for_delete` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=gbk
- 1 row in set (0.02 sec)
使用delect from这种方式清空表的内容,不会改变自增值。
语法:
TRUNCATE [TABLE] table_name
- --准备测试表
- mysql> CREATE TABLE for_truncate (
- -> id INT PRIMARY KEY AUTO_INCREMENT,
- -> name VARCHAR(20)
- -> );
- Query OK, 0 rows affected (0.14 sec)
- --插入测试数据
- mysql> INSERT INTO for_truncate (name) VALUES ('A'), ('B'), ('C');
- Query OK, 3 rows affected (0.04 sec)
- Records: 3 Duplicates: 0 Warnings: 0
- --查看表结构
- mysql> select* from for_truncate;
- +----+------+
- | id | name |
- +----+------+
- | 1 | A |
- | 2 | B |
- | 3 | C |
- +----+------+
- 3 rows in set (0.01 sec)
- --查看创建表时的SQL,可以发现,下一次自增的id值是4
- 5mysql> show create table for_truncate\G;
- *************************** 1. row ***************************
- Table: for_truncate
- Create Table: CREATE TABLE `for_truncate` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=gbk
- 1 row in set (0.01 sec)
- --删除表中数据
- mysql> truncate for_truncate;
- Query OK, 0 rows affected (0.21 sec)
- --查看创建表时的SQL,发现AUTO_INCREMENT字段没了
- mysql> show create table for_truncate\G;
- *************************** 1. row ***************************
- Table: for_truncate
- Create Table: CREATE TABLE `for_truncate` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB DEFAULT CHARSET=gbk
- 1 row in set (0.01 sec)
- --新插入一条数据
- mysql> insert into for_truncate (name) values ('E');
- Query OK, 1 row affected (0.04 sec)
- --查看表结构,发现id从1开始
- mysql> select* from for_truncate;
- +----+------+
- | id | name |
- +----+------+
- | 1 | E |
- +----+------+
- 1 row in set (0.00 sec)
- --查看创建表的SQL,出现自增字段,下一次自增值是2
- mysql> show create table for_truncate\G;
- *************************** 1. row ***************************
- Table: for_truncate
- Create Table: CREATE TABLE `for_truncate` (
- `id` int(11) NOT NULL AUTO_INCREMENT,
- `name` varchar(20) DEFAULT NULL,
- PRIMARY KEY (`id`)
- ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=gbk
- 1 row in set (0.00 sec)
truncate操作慎用
1. 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
2. MySQL不会把truncate的操作记录记录在日志里(DELETE会),所以它比 DELETE 更快,但是TRUNCATE在删除数据的时候,并不经过真正的事物,所以无法回滚
3. truncate在清空表时,会初始化自增值。
INSERT INTO table_name [(column [, column ...])] SELECT ...
制造一份原始数据:
- --创建表结构
- mysql> CREATE TABLE duplicate_table (id int, name varchar(20));
- Query OK, 0 rows affected (0.26 sec)
- --插入测试数据
- mysql> INSERT INTO duplicate_table VALUES
- -> (100, 'aaa'),
- -> (100, 'aaa'),
- -> (200, 'bbb'),
- -> (200, 'bbb'),
- -> (200, 'bbb'),
- -> (300, 'ccc');
- Query OK, 6 rows affected (0.03 sec)
- Records: 6 Duplicates: 0 Warnings: 0
去重思路:1、创建一张属性和原表一样的空表
- --创建一张属性和duplicate_table一样的表no_duplicate_table(空表)
- mysql> create table no_duplicate_table like duplicate_table;
- Query OK, 0 rows affected (0.23 sec)
- --它是空表
- mysql> select* from no_duplicate_table;
- Empty set (0.01 sec)
- --但是属性和duplicate_table一样
- mysql> desc no_duplicate_table;
- +-------+-------------+------+-----+---------+-------+
- | Field | Type | Null | Key | Default | Extra |
- +-------+-------------+------+-----+---------+-------+
- | id | int(11) | YES | | NULL | |
- | name | varchar(20) | YES | | NULL | |
- +-------+-------------+------+-----+---------+-------+
- 2 rows in set (0.02 sec)
2、利用distinct筛选出原表中去重后的数据
- --对原表select出来的结果insert进新表中
- mysql> insert into no_duplicate_table select distinct * from duplicate_table;
- Query OK, 3 rows affected (0.05 sec)
- Records: 3 Duplicates: 0 Warnings: 0
- --查看新表数据
- mysql> select* from no_duplicate_table;
- +------+------+
- | id | name |
- +------+------+
- | 100 | aaa |
- | 200 | bbb |
- | 300 | ccc |
- +------+------+
- 3 rows in set (0.01 sec)
3、将原表名字修改为其他,将新表数据修改为原表名字(狸猫换太子)
- --改名
- mysql> rename table duplicate_table to old_duplicate_table,no_duplicate_table to duplicate_table;
- Query OK, 0 rows affected (0.17 sec)
- --查看表
- mysql> select* from duplicate_table;
- +------+------+
- | id | name |
- +------+------+
- | 100 | aaa |
- | 200 | bbb |
- | 300 | ccc |
- +------+------+
- 3 rows in set (0.02 sec)
我们在改名前已经准备好了新表,通过重命名表,实现原子的去重操作。
这里的rename改名就是单纯的改名,其实就是文件名和inode的映射关系的改变。
函数 | 说明 |
COUNT([DISTINCT] expr) | 返回查询到的数据的 数量 |
SUM([DISTINCT] expr) | 返回查询到的数据的 总和,不是数字没有意义 |
AVG([DISTINCT] expr) | 返回查询到的数据的 平均值,不是数字没有意义 |
MAX([DISTINCT] expr) | 返回查询到的数据的 最大值,不是数字没有意义 |
MIN([DISTINCT] expr) | 返回查询到的数据的 最小值,不是数字没有意义 |
- mysql> select* from old_duplicate_table;;
- +------+------+
- | id | name |
- +------+------+
- | 100 | aaa |
- | 100 | aaa |
- | 200 | bbb |
- | 200 | bbb |
- | 200 | bbb |
- | 300 | ccc |
- +------+------+
- 6 rows in set (0.01 sec)
- --统计去重的名字有几个
- mysql> select count(distinct name) 总数 from old_duplicate_table;
- +--------+
- | 总数 |
- +--------+
- | 3 |
- +--------+
- 1 row in set (0.00 sec)
- --统计共有几行
- mysql> select count(*) from old_duplicate_table;
- +----------+
- | count(*) |
- +----------+
- | 6 |
- +----------+
- 1 row in set (0.00 sec)
- --统计共有几行
- mysql> select count(2) from old_duplicate_table;
- +----------+
- | count(2) |
- +----------+
- | 6 |
- +----------+
- 1 row in set (0.00 sec)
- --统计id小于200的行数
- mysql> select count(*) from old_duplicate_table where id<200;
- +----------+
- | count(*) |
- +----------+
- | 2 |
- +----------+
- 1 row in set (0.01 sec)
- --统计id和
- mysql> select sum(id) from old_duplicate_table;
- +---------+
- | sum(id) |
- +---------+
- | 1100 |
- +---------+
- 1 row in set (0.00 sec)
- --统计id的平均值
- mysql> select sum(id)/count(*) from old_duplicate_table;
- +------------------+
- | sum(id)/count(*) |
- +------------------+
- | 183.3333 |
- +------------------+
- 1 row in set (0.00 sec)
- --统计id的平均值
- mysql> select avg(id) from old_duplicate_table;
- +----------+
- | avg(id) |
- +----------+
- | 183.3333 |
- +----------+
- 1 row in set (0.00 sec)
4、MAX([DISTINCT] expr) 返回查询到的数据的 最大值,不是数字没有意义
- --查找最小的id
- mysql> select min(id) from old_duplicate_table;
- +---------+
- | min(id) |
- +---------+
- | 100 |
- +---------+
- 1 row in set (0.01 sec)
- --查找id大于150的最小值
- mysql> select min(id) from old_duplicate_table where id>150;
- +---------+
- | min(id) |
- +---------+
- | 200 |
- +---------+
- 1 row in set (0.00 sec)
分组的意义是为了聚合统计。
select column1, column2, .. from table group by column;
- --将linux目录下的sql表导入MySQL
- mysql> source /home/jly/scott_data.sql;
-
- mysql> use scott;
- Database changed
-
- mysql> show tables;
- +-----------------+
- | Tables_in_scott |
- +-----------------+
- | dept |
- | emp |
- | salgrade |
- +-----------------+
创建一个雇员信息表(来自oracle 9i的经典测试表)
EMP员工表
DEPT部门表
SALGRADE工资等级表
- DROP database IF EXISTS `scott`;
- CREATE database IF NOT EXISTS `scott` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;
-
- USE `scott`;
-
- DROP TABLE IF EXISTS `dept`;
- CREATE TABLE `dept` (
- `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
- `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
- `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
- );
-
-
- DROP TABLE IF EXISTS `emp`;
- CREATE TABLE `emp` (
- `empno` int(6) unsigned zerofill NOT NULL COMMENT '雇员编号',
- `ename` varchar(10) DEFAULT NULL COMMENT '雇员姓名',
- `job` varchar(9) DEFAULT NULL COMMENT '雇员职位',
- `mgr` int(4) unsigned zerofill DEFAULT NULL COMMENT '雇员领导编号',
- `hiredate` datetime DEFAULT NULL COMMENT '雇佣时间',
- `sal` decimal(7,2) DEFAULT NULL COMMENT '工资月薪',
- `comm` decimal(7,2) DEFAULT NULL COMMENT '奖金',
- `deptno` int(2) unsigned zerofill DEFAULT NULL COMMENT '部门编号'
- );
-
-
- DROP TABLE IF EXISTS `salgrade`;
- CREATE TABLE `salgrade` (
- `grade` int(11) DEFAULT NULL COMMENT '等级',
- `losal` int(11) DEFAULT NULL COMMENT '此等级最低工资',
- `hisal` int(11) DEFAULT NULL COMMENT '此等级最高工资'
- );
-
-
- insert into dept (deptno, dname, loc)
- values (10, 'ACCOUNTING', 'NEW YORK');
- insert into dept (deptno, dname, loc)
- values (20, 'RESEARCH', 'DALLAS');
- insert into dept (deptno, dname, loc)
- values (30, 'SALES', 'CHICAGO');
- insert into dept (deptno, dname, loc)
- values (40, 'OPERATIONS', 'BOSTON');
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7369, 'SMITH', 'CLERK', 7902, '1980-12-17', 800, null, 20);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7499, 'ALLEN', 'SALESMAN', 7698, '1981-02-20', 1600, 300, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7521, 'WARD', 'SALESMAN', 7698, '1981-02-22', 1250, 500, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7566, 'JONES', 'MANAGER', 7839, '1981-04-02', 2975, null, 20);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7654, 'MARTIN', 'SALESMAN', 7698, '1981-09-28', 1250, 1400, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7698, 'BLAKE', 'MANAGER', 7839, '1981-05-01', 2850, null, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7782, 'CLARK', 'MANAGER', 7839, '1981-06-09', 2450, null, 10);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7788, 'SCOTT', 'ANALYST', 7566, '1987-04-19', 3000, null, 20);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7839, 'KING', 'PRESIDENT', null, '1981-11-17', 5000, null, 10);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7844, 'TURNER', 'SALESMAN', 7698,'1981-09-08', 1500, 0, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7876, 'ADAMS', 'CLERK', 7788, '1987-05-23', 1100, null, 20);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7900, 'JAMES', 'CLERK', 7698, '1981-12-03', 950, null, 30);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7902, 'FORD', 'ANALYST', 7566, '1981-12-03', 3000, null, 20);
-
- insert into emp (empno, ename, job, mgr, hiredate, sal, comm, deptno)
- values (7934, 'MILLER', 'CLERK', 7782, '1982-01-23', 1300, null, 10);
-
- insert into salgrade (grade, losal, hisal) values (1, 700, 1200);
- insert into salgrade (grade, losal, hisal) values (2, 1201, 1400);
- insert into salgrade (grade, losal, hisal) values (3, 1401, 2000);
- insert into salgrade (grade, losal, hisal) values (4, 2001, 3000);
- insert into salgrade (grade, losal, hisal) values (5, 3001, 9999);
- mysql> select* from emp;
- +--------+--------+-----------+------+---------------------+---------+---------+--------+
- | empno | ename | job | mgr | hiredate | sal | comm | deptno |
- +--------+--------+-----------+------+---------------------+---------+---------+--------+
- | 007369 | SMITH | CLERK | 7902 | 1980-12-17 00:00:00 | 800.00 | NULL | 20 |
- | 007499 | ALLEN | SALESMAN | 7698 | 1981-02-20 00:00:00 | 1600.00 | 300.00 | 30 |
- | 007521 | WARD | SALESMAN | 7698 | 1981-02-22 00:00:00 | 1250.00 | 500.00 | 30 |
- | 007566 | JONES | MANAGER | 7839 | 1981-04-02 00:00:00 | 2975.00 | NULL | 20 |
- | 007654 | MARTIN | SALESMAN | 7698 | 1981-09-28 00:00:00 | 1250.00 | 1400.00 | 30 |
- | 007698 | BLAKE | MANAGER | 7839 | 1981-05-01 00:00:00 | 2850.00 | NULL | 30 |
- | 007782 | CLARK | MANAGER | 7839 | 1981-06-09 00:00:00 | 2450.00 | NULL | 10 |
- | 007788 | SCOTT | ANALYST | 7566 | 1987-04-19 00:00:00 | 3000.00 | NULL | 20 |
- | 007839 | KING | PRESIDENT | NULL | 1981-11-17 00:00:00 | 5000.00 | NULL | 10 |
- | 007844 | TURNER | SALESMAN | 7698 | 1981-09-08 00:00:00 | 1500.00 | 0.00 | 30 |
- | 007876 | ADAMS | CLERK | 7788 | 1987-05-23 00:00:00 | 1100.00 | NULL | 20 |
- | 007900 | JAMES | CLERK | 7698 | 1981-12-03 00:00:00 | 950.00 | NULL | 30 |
- | 007902 | FORD | ANALYST | 7566 | 1981-12-03 00:00:00 | 3000.00 | NULL | 20 |
- | 007934 | MILLER | CLERK | 7782 | 1982-01-23 00:00:00 | 1300.00 | NULL | 10 |
- +--------+--------+-----------+------+---------------------+---------+---------+--------+
- 14 rows in set (0.00 sec)
- --按部门对各部门的平均工资和最高工资进行统计
- mysql> select deptno,avg(sal),max(sal) from emp group by deptno;
- +--------+-------------+----------+
- | deptno | avg(sal) | max(sal) |
- +--------+-------------+----------+
- | 10 | 2916.666667 | 5000.00 |
- | 20 | 2175.000000 | 3000.00 |
- | 30 | 1566.666667 | 2850.00 |
- +--------+-------------+----------+
- 3 rows in set (0.01 sec)
多个分组条件的分组查询:
- mysql> select deptno,job,avg(sal),max(sal) from emp group by deptno,job;
- +--------+-----------+-------------+----------+
- | deptno | job | avg(sal) | max(sal) |
- +--------+-----------+-------------+----------+
- | 10 | CLERK | 1300.000000 | 1300.00 |
- | 10 | MANAGER | 2450.000000 | 2450.00 |
- | 10 | PRESIDENT | 5000.000000 | 5000.00 |
- | 20 | ANALYST | 3000.000000 | 3000.00 |
- | 20 | CLERK | 950.000000 | 1100.00 |
- | 20 | MANAGER | 2975.000000 | 2975.00 |
- | 30 | CLERK | 950.000000 | 950.00 |
- | 30 | MANAGER | 2850.000000 | 2850.00 |
- | 30 | SALESMAN | 1400.000000 | 1600.00 |
- +--------+-----------+-------------+----------+
- 9 rows in set (0.00 sec)
如果在select筛选后面加一个ename的筛选字段,将报错:
1、先统计每一个部门的平均工资(先按部门对平均工资进行分组聚合)
2、再使用having对聚合的结果进行条件判断
- mysql> select deptno,avg(sal) as 平均工资 from emp group by deptno having 平均工资<2000;
- +--------+--------------+
- | deptno | 平均工资 |
- +--------+--------------+
- | 30 | 1566.666667 |
- +--------+--------------+
- mysql> select deptno,job,avg(sal) 平均工资 from emp where ename!='SMITH' group by deptno,job having 平均工资<2000;
- +--------+----------+--------------+
- | deptno | job | 平均工资 |
- +--------+----------+--------------+
- | 10 | CLERK | 1300.000000 |
- | 20 | CLERK | 1100.000000 |
- | 30 | CLERK | 950.000000 |
- | 30 | SALESMAN | 1400.000000 |
- +--------+----------+--------------+
- 4 rows in set (0.01 sec)
1、having和where都可以进行条件筛选,分组聚合只能使用having不能使用where,但是只有一张表的的筛选既可以用having也可用where,但是这种场景不建议使用having(为了区分,不建议混用,where的活让where干)
2、筛选的对象不同,如下图:
3、条件筛选的顺序不同,如下图:
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。