MySQL快速入门——基本查询(下)

MySQL快速入门------基本查询(下)

  • [1. Update(更新)](#1. Update(更新))
    • [1.1 将孙悟空同学的数学成绩变更为 80](#1.1 将孙悟空同学的数学成绩变更为 80)
    • [1.2 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分](#1.2 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分)
    • [1.3 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分](#1.3 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分)
    • [1.4 将所有同学的语文成绩更新为原来的 2 倍](#1.4 将所有同学的语文成绩更新为原来的 2 倍)
  • [2. Delete(删除)](#2. Delete(删除))
    • [2.1 删除孙悟空同学的考试成绩](#2.1 删除孙悟空同学的考试成绩)
      • [2.1.2 删除整张表数据](#2.1.2 删除整张表数据)
      • [2.1.2 截断表](#2.1.2 截断表)
  • [3. 插入查询结果](#3. 插入查询结果)
  • [4. 聚合函数](#4. 聚合函数)
    • [4.1 统计班级共有多少同学](#4.1 统计班级共有多少同学)
    • [4.2 统计班级收集的 qq 号有多少](#4.2 统计班级收集的 qq 号有多少)
    • [4.3 统计本次考试的数学成绩分数个数](#4.3 统计本次考试的数学成绩分数个数)
    • [4.4 统计数学成绩总分](#4.4 统计数学成绩总分)
    • [4.5 统计平均总分](#4.5 统计平均总分)
    • [4.6 返回英语最高分](#4.6 返回英语最高分)
    • [4.7 返回 > 70 分以上的数学最低分](#4.7 返回 > 70 分以上的数学最低分)
  • [5. group by 子句的使用](#5. group by 子句的使用)
    • [5.1 如何显示每个部门的平均工资和最高工资](#5.1 如何显示每个部门的平均工资和最高工资)
    • [5.2 显示每个部门的每种岗位的平均工资和最低工资](#5.2 显示每个部门的每种岗位的平均工资和最低工资)
    • [5.3 显示平均工资低于2000的部门和它的平均工资(重点)](#5.3 显示平均工资低于2000的部门和它的平均工资(重点))
    • [5.4 显示平均工资低于2500的部门和它的平均工资,将编号为20的部门排除在外(重点)](#5.4 显示平均工资低于2500的部门和它的平均工资,将编号为20的部门排除在外(重点))
  • [6. 一切皆表](#6. 一切皆表)

CRUD : Create(创建),Retrieve(读取),Update(更新),Delete(删除)


1. Update(更新)


1. 语法:

sql 复制代码
UPDATE table_name SET column = expr [, column = expr ...]
	[WHERE ...] [ORDER BY ...] [LIMIT ...]

2. 要用到的表 exam_result:

  • 这个表在基本查询(上)就有使用。
sql 复制代码
mysql> select * from exam_result;
+----+-----------+---------+------+---------+
| 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 |
|  6 | 孙权      |      70 |   73 |      78 |
|  7 | 宋公明    |      75 |   65 |      30 |
+----+-----------+---------+------+---------+
7 rows in set (0.01 sec)

1.1 将孙悟空同学的数学成绩变更为 80


sql 复制代码
-- 查看原数据
mysql> SELECT name, math FROM exam_result WHERE name = '孙悟空';
+-----------+------+
| name      | math |
+-----------+------+
| 孙悟空    |   78 |
+-----------+------+
1 row in set (0.00 sec)

-- 数据更新
mysql> UPDATE exam_result SET math = 80 WHERE name = '孙悟空';
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

-- 查看更新后数据
mysql> SELECT name, math FROM exam_result WHERE name = '孙悟空';
+-----------+------+
| name      | math |
+-----------+------+
| 孙悟空    |   80 |
+-----------+------+
1 row in set (0.00 sec)

1.2 将曹孟德同学的数学成绩变更为 60 分,语文成绩变更为 70 分


sql 复制代码
mysql> select name, math, chinese from exam_result where name='曹孟德';
+-----------+------+---------+
| name      | math | chinese |
+-----------+------+---------+
| 曹孟德    |   84 |      82 |
+-----------+------+---------+
1 row in set (0.00 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> select name, math, chinese from exam_result where name='曹孟德';
+-----------+------+---------+
| name      | math | chinese |
+-----------+------+---------+
| 曹孟德    |   60 |      70 |
+-----------+------+---------+
1 row in set (0.00 sec)

1.3 将总成绩倒数前三的 3 位同学的数学成绩加上 30 分


sql 复制代码
-- 先查看一下倒数前三名是谁
mysql> select name, math+english+chinese total from exam_result order by total asc limit 3;
+-----------+-------+
| name      | total |
+-----------+-------+
| 宋公明    |   170 |
| 刘玄德    |   185 |
| 曹孟德    |   197 |
+-----------+-------+
3 rows in set (0.00 sec)

-- 更新数据时,不能使用math+=30
mysql> update exam_result set math=math+30 order by math+english+chinese asc limit 3;
Query OK, 3 rows affected (0.01 sec)
Rows matched: 3  Changed: 3  Warnings: 0

-- 此时倒数前三名已经改变
mysql> select name, math+english+chinese total from exam_result order by total asc limit 3;
+-----------+-------+
| name      | total |
+-----------+-------+
| 宋公明    |   200 |
| 刘玄德    |   215 |
| 唐三藏    |   221 |
+-----------+-------+
3 rows in set (0.00 sec)

-- 看看之前的倒数前三名math成绩是否按要求改变了
mysql> select name, math+english+chinese total from exam_result 
    -> where name in ('宋公明', '刘玄德', '曹孟德');
+-----------+-------+
| name      | total |
+-----------+-------+
| 曹孟德    |   227 |
| 刘玄德    |   215 |
| 宋公明    |   200 |
+-----------+-------+
3 rows in set (0.01 sec)

1.4 将所有同学的语文成绩更新为原来的 2 倍


更新全表的操作和删除一样危险,要慎之又慎。

sql 复制代码
mysql> select * from exam_result;
+----+-----------+---------+------+---------+
| id | name      | chinese | math | english |
+----+-----------+---------+------+---------+
|  1 | 唐三藏    |      67 |   98 |      56 |
|  2 | 孙悟空    |      87 |   80 |      77 |
|  3 | 猪悟能    |      88 |   98 |      90 |
|  4 | 曹孟德    |      70 |   90 |      67 |
|  5 | 刘玄德    |      55 |  115 |      45 |
|  6 | 孙权      |      70 |   73 |      78 |
|  7 | 宋公明    |      75 |   95 |      30 |
+----+-----------+---------+------+---------+
7 rows in set (0.00 sec)

mysql> update exam_result set chinese=chinese*2;
Query OK, 7 rows affected (0.01 sec)
Rows matched: 7  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 |   90 |      67 |
|  5 | 刘玄德    |     110 |  115 |      45 |
|  6 | 孙权      |     140 |   73 |      78 |
|  7 | 宋公明    |     150 |   95 |      30 |
+----+-----------+---------+------+---------+
7 rows in set (0.00 sec)

2. Delete(删除)


语法:

sql 复制代码
DELETE FROM table_name [WHERE ...] [ORDER BY ...] [LIMIT ...]

2.1 删除孙悟空同学的考试成绩


sql 复制代码
mysql> select * from exam_result where name='孙悟空';
+----+-----------+---------+------+---------+
| id | name      | chinese | math | english |
+----+-----------+---------+------+---------+
|  2 | 孙悟空    |     174 |   80 |      77 |
+----+-----------+---------+------+---------+
1 row in set (0.00 sec)

mysql> delete from exam_result where name='孙悟空';
Query OK, 1 row affected (0.01 sec)

mysql> select * from exam_result where name='孙悟空';
Empty set (0.00 sec)

mysql> select * from exam_result;
+----+-----------+---------+------+---------+
| id | name      | chinese | math | english |
+----+-----------+---------+------+---------+
|  1 | 唐三藏    |     134 |   98 |      56 |
|  3 | 猪悟能    |     176 |   98 |      90 |
|  4 | 曹孟德    |     140 |   90 |      67 |
|  5 | 刘玄德    |     110 |  115 |      45 |
|  6 | 孙权      |     140 |   73 |      78 |
|  7 | 宋公明    |     150 |   95 |      30 |
+----+-----------+---------+------+---------+
6 rows in set (0.00 sec)

2.1.2 删除整张表数据


  • 准备表和数据:
sql 复制代码
-- 准备测试表
mysql> CREATE TABLE for_delete (
	-> id INT PRIMARY KEY AUTO_INCREMENT,
	-> name VARCHAR(20)
	-> );
Query OK, 0 rows affected (0.16 sec)

-- 插入测试数据
mysql> INSERT INTO for_delete (name) VALUES ('A'), ('B'), ('C');
Query OK, 3 rows affected (1.05 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 复制代码
mysql> DELETE FROM for_delete;
Query OK, 3 rows affected (0.01 sec)

mysql> SELECT * FROM for_delete;
Empty set (0.00 sec)
  • 观察自增键的变化,AUTO_INCREMENT 不变:
sql 复制代码
-- 再插入一条数据,自增 id 在原值上增长
mysql> INSERT INTO for_delete (name) VALUES ('D');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM for_delete;
+----+------+
| id | name |
+----+------+
|  4 | D    |
+----+------+
1 row in set (0.00 sec)

-- 查看表结构,会有 AUTO_INCREMENT=n 项
mysql> SHOW CREATE TABLE for_delete\G
*************************** 1. row ***************************
       Table: for_delete
Create Table: CREATE TABLE `for_delete` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.01 sec)

2.1.2 截断表


1. 语法:

sql 复制代码
TRUNCATE [TABLE] table_name

2. 注意:这个操作慎用

  • 只能对整表操作,不能像 DELETE 一样针对部分数据操作;
  • 实际上 MySQL 不对数据操作,所以比 DELETE 更快,但是 TRUNCATE 在删除数据的时候,并不经过真正的事物,所以无法回滚(该操作不写入日志,所以无法回滚);
  • 会重置 AUTO_INCREMENT 项。

3. 案例:

  • 准备表和数据:
sql 复制代码
-- 建表
CREATE TABLE for_truncate (
	id INT PRIMARY KEY AUTO_INCREMENT,
	name VARCHAR(20)
);

-- 插入三个数据
mysql> INSERT INTO for_truncate (name) VALUES ('A'), ('B'), ('C');
Query OK, 3 rows affected (0.01 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.00 sec)
  • 截断表:
sql 复制代码
mysql> truncate for_truncate;
Query OK, 0 rows affected (0.05 sec)

mysql> SELECT * FROM for_truncate;
Empty set (0.01 sec)
  • 观察自增键变化,AUTO_INCREMENT 被重置:
sql 复制代码
-- 再插入一条数据,自增 id 在重新增长
mysql> INSERT INTO for_truncate (name) VALUES ('D');
Query OK, 1 row affected (0.02 sec)

mysql> SELECT * FROM for_truncate;
+----+------+
| id | name |
+----+------+
|  1 | D    |
+----+------+
1 row in set (0.00 sec)

-- 查看表结构,会有 AUTO_INCREMENT=2 项
mysql> SHOW CREATE TABLE for_truncate\G
*************************** 1. row ***************************
       Table: for_truncate
Create Table: CREATE TABLE `for_truncate` (
  `id` int NOT NULL AUTO_INCREMENT,
  `name` varchar(20) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci
1 row in set (0.00 sec)

3. 插入查询结果


1. 语法:

sql 复制代码
INSERT INTO table_name [(column [, column ...])] SELECT ...

2. 案例:删除表中的的重复复记录,重复的数据只能有一份

思路:

  1. 先创建一张空表,结构和要删除的表结构一样;
  2. 将原表中的数据去重,插入到新表中;
  3. 重命名,先将原表名字改成别的,再将新表名字改成原表名字。
  • 准备数据:
sql 复制代码
-- 创建原数据表
mysql> CREATE TABLE duplicate_table (id int, name varchar(20));
Query OK, 0 rows affected (0.01 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.00 sec)
Records: 6 Duplicates: 0 Warnings: 0
  • 开始操作:
sql 复制代码
-- 创建一张空表 no_duplicate_table,结构和 duplicate_table 一样
mysql> create table no_duplicate_table like duplicate_table;
Query OK, 0 rows affected (0.04 sec)

-- 将 duplicate_table 的去重数据插入到 no_duplicate_table
mysql> insert into no_duplicate_table select distinct * from duplicate_table;
Query OK, 3 rows affected (0.01 sec)
Records: 3  Duplicates: 0  Warnings: 0

-- 通过重命名表,实现原子的去重操作
mysql> RENAME TABLE duplicate_table TO old_duplicate_table,
    -> no_duplicate_table TO duplicate_table;
Query OK, 0 rows affected (0.05 sec)

-- 查看最终结果
mysql> SELECT * FROM duplicate_table;
+------+------+
| id   | name |
+------+------+
|  100 | aaa  |
|  200 | bbb  |
|  300 | ccc  |
+------+------+
3 rows in set (0.00 sec)

4. 聚合函数


函数 说明
COUNT(DISTINCT expr) 返回查询到的数据的 数量
SUM(DISTINCT expr) 返回查询到的数据的 总和,不是数字没有意义
AVG(DISTINCT expr) 返回查询到的数据的 平均值,不是数字没有意义
MAX(DISTINCT expr) 返回查询到的数据的 最大值,不是数字没有意义
MIN(DISTINCT expr) 返回查询到的数据的 最小值,不是数字没有意义

用到的表

sql 复制代码
mysql> select * from students;
+-----+-------+-----------+-------+
| id  | sn    | name      | qq    |
+-----+-------+-----------+-------+
| 100 | 10010 | 唐大师    | NULL  |
| 101 | 10001 | 孙悟空    | 11111 |
| 103 | 20002 | 孙仲谋    | NULL  |
| 105 | 20001 | 曹阿瞒    | NULL  |
+-----+-------+-----------+-------+
4 rows in set (0.00 sec)

4.1 统计班级共有多少同学


统计表有多少行

sql 复制代码
-- 使用 * 做统计,不受 NULL 影响
mysql> select count(*) from students;
+----------+
| count(*) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

-- 使用表达式做统计
mysql> select count(1) from students;
+----------+
| count(1) |
+----------+
|        4 |
+----------+
1 row in set (0.00 sec)

4.2 统计班级收集的 qq 号有多少


sql 复制代码
-- NULL不计入结果
mysql> SELECT COUNT(qq) FROM students;
+-----------+
| COUNT(qq) |
+-----------+
|         1 |
+-----------+
1 row in set (0.00 sec)

4.3 统计本次考试的数学成绩分数个数


sql 复制代码
-- COUNT(math) 统计的是全部成绩
mysql> SELECT COUNT(math) FROM exam_result;
+-------------+
| COUNT(math) |
+-------------+
|           6 |
+-------------+
1 row in set (0.00 sec)

-- COUNT(DISTINCT math) 统计的是去重的成绩数量
mysql> SELECT COUNT(DISTINCT math) FROM exam_result;
+----------------------+
| COUNT(DISTINCT math) |
+----------------------+
|                    5 |
+----------------------+
1 row in set (0.00 sec)

4.4 统计数学成绩总分


sql 复制代码
mysql> SELECT SUM(math) FROM exam_result;
+-----------+
| SUM(math) |
+-----------+
|       569 |
+-----------+
1 row in set (0.00 sec)

-- 不及格 < 60 的总分,没有结果,返回 NULL
mysql> SELECT SUM(math) FROM exam_result WHERE math < 60;
+-----------+
| SUM(math) |
+-----------+
|      NULL |
+-----------+
1 row in set (0.00 sec)

4.5 统计平均总分


sql 复制代码
mysql> SELECT AVG(chinese + math + english) 平均总分 FROM exam_result;
+--------------+
| 平均总分     |
+--------------+
|        297.5 |
+--------------+
1 row in set (0.00 sec)

4.6 返回英语最高分


sql 复制代码
mysql> SELECT MAX(english) FROM exam_result;
+--------------+
| MAX(english) |
+--------------+
|           90 |
+--------------+
1 row in set (0.00 sec)

4.7 返回 > 70 分以上的数学最低分


sql 复制代码
mysql> SELECT MIN(math) FROM exam_result WHERE math > 70;
+-----------+
| MIN(math) |
+-----------+
|        73 |
+-----------+
1 row in set (0.00 sec)

5. group by 子句的使用


1. 在 select 中使用 group by 子句可以对指定列进行分组查询

sql 复制代码
select column1, column2, .. from table group by column;

2. 案例:

  • 准备工作,创建一个雇员信息表(来自oracle 9i的经典测试表)
    • EMP员工表;
    • DEPT部门表;
    • SALGRADE工资等级表。

将下面这个 scott_data.sql 文件,在mysql内 source 执行,即可获得准备数据。

sql 复制代码
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);
  • 下面看一眼这个数据库中的数据:
sql 复制代码
mysql> use scott;
Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Database changed
mysql> show tables;
+-----------------+
| Tables_in_scott |
+-----------------+
| dept            |
| emp             |
| salgrade        |
+-----------------+
3 rows in set (0.00 sec)
  • 看一眼各个表之间的关系:
    • salgrade薪水表,emp员工表,dept部门表。
sql 复制代码
mysql> show create table salgrade\G
*************************** 1. row ***************************
       Table: salgrade
Create Table: CREATE TABLE `salgrade` (
  `grade` int DEFAULT NULL COMMENT '等级',
  `losal` int DEFAULT NULL COMMENT '此等级最低工资',
  `hisal` int DEFAULT NULL COMMENT '此等级最高工资'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)

mysql> show create table emp\G
*************************** 1. row ***************************
       Table: emp
Create Table: 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 '部门编号'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)

mysql> show create table dept\G
*************************** 1. row ***************************
       Table: dept
Create Table: CREATE TABLE `dept` (
  `deptno` int(2) unsigned zerofill NOT NULL COMMENT '部门编号',
  `dname` varchar(14) DEFAULT NULL COMMENT '部门名称',
  `loc` varchar(13) DEFAULT NULL COMMENT '部门所在地点'
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3
1 row in set (0.00 sec)

5.1 如何显示每个部门的平均工资和最高工资


sql 复制代码
mysql> select deptno, avg(sal), max(sal) from emp group by deptno;
+--------+-------------+----------+
| deptno | avg(sal)    | max(sal) |
+--------+-------------+----------+
|     20 | 2175.000000 |  3000.00 |
|     30 | 1566.666667 |  2850.00 |
|     10 | 2916.666667 |  5000.00 |
+--------+-------------+----------+
3 rows in set (0.00 sec)

注意:

  • 经过分组 group by 后,select 后能显示的内容只有两块:
    *
    1. group by 后跟的列,比如上述例子就是 deptno
      1. 聚合函数。
  • 写其他内容比如 empno 统统报错,这样的显示方式在逻辑上也是行不通的。

5.2 显示每个部门的每种岗位的平均工资和最低工资


sql 复制代码
mysql> select deptno, job, avg(sal), max(sal) from emp group by deptno, job order by deptno;
+--------+-----------+-------------+----------+
| 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)

5.3 显示平均工资低于2000的部门和它的平均工资(重点)


  • 统计各个部门的平均工资:
sql 复制代码
mysql> select deptno, avg(sal) from emp group by deptno;
+--------+-------------+
| deptno | avg(sal)    |
+--------+-------------+
|     20 | 2175.000000 |
|     30 | 1566.666667 |
|     10 | 2916.666667 |
+--------+-------------+
3 rows in set (0.00 sec)
  • havinggroup by 配合使用,对 group by 结果进行过滤:
sql 复制代码
mysql> select deptno, avg(sal) avg_sal from emp group by deptno having avg_sal<2000;
+--------+-------------+
| deptno | avg_sal     |
+--------+-------------+
|     30 | 1566.666667 |
+--------+-------------+
1 row in set (0.00 sec)

5.4 显示平均工资低于2500的部门和它的平均工资,将编号为20的部门排除在外(重点)


sql 复制代码
mysql> select deptno, avg(sal) avg_sal from emp where deptno <> 20 group by deptno having avg_sal<2500;
+--------+-------------+
| deptno | avg_sal     |
+--------+-------------+
|     30 | 1566.666667 |
+--------+-------------+
1 row in set (0.00 sec)

下面我们来详细解释一下,group by 和 where 的区别

  • 侧重点不同:
  • 条件筛选阶段不同:
    *
    1. 先执行 from 指明去哪个表筛选;2. 再执行 where 拿到原始表筛选条件;3. group by 进行分组;4. 聚合函数执行,进行聚合;5. having 执行,对分组聚合结果进行筛选。

6. 一切皆表


不要单纯的认为,只有磁盘上表结构导入到mysql中,真实存在的表,才叫表。中间筛选出来的,包括最终结果,在我看来,全都是逻辑上的表!"MySQL"一切皆表。

未来只要我们能够处理好单表的CURD,所有sql场景,我们全部都能用同一的方式进行(后面讲)。


相关推荐
Yeyu20 分钟前
刷新一帧的艺术:invalidate / postInvalidate / postInvalidateOnAnimation全解析
android
潘潘潘2 小时前
Android OTA 升级原理和流程介绍
android
plainGeekDev8 小时前
null 判断 → Kotlin 可空类型
android·java·kotlin
plainGeekDev8 小时前
getter/setter → Kotlin 属性
android·java·kotlin
云技纵横9 小时前
Gap Lock 死锁实战:5 秒在本地复现 MySQL 间隙锁死锁
后端·mysql
YXL1111YXL9 小时前
Handler 消息回收与协程异步执行的时序陷阱
android
无响应de神9 小时前
三、用户与权限管理
数据库·mysql
恋猫de小郭10 小时前
KMP / CMP 鸿蒙版本 Beta 发布,他有什么特别之处?
android·前端·flutter
三少爷的鞋11 小时前
Android 协程并发控制:别动线程池,控制好并发语义就够了
android