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场景,我们全部都能用同一的方式进行(后面讲)。


相关推荐
我叫黑大帅8 小时前
MySQL 并发插入竞态问题:原子写入实践指南
后端·mysql·面试
我会尽全力 乐观而坚强9 小时前
MySQL零基础入门(二)
数据库·mysql·adb
龙石数据12 小时前
MySQL 全量同步到 Hive 怎么做?三步配置教程
数据库·hive·mysql·数据治理·数据中台
2601_9637713713 小时前
Offloading WP-Cron and Securing Ticket Webhooks on Enterprise IT Sites
android
花燃柳卧14 小时前
跨平台路由组件工程源码补充上传
android·flutter·kotlin
apihz14 小时前
随机驾考题目(C 照科一 / 科四 2000+ 题)免费API调用教程
android·java·c语言·开发语言·网络协议·tcp/ip
宸翰15 小时前
uni-app 设置 Android 底部虚拟导航栏背景色
android·前端·uni-app
TechNomad15 小时前
Kotlin类对象与接口详解
android·kotlin
白露与泡影16 小时前
慢 SQL 不一定是 SQL 慢:一次 MySQL 连接池耗尽的故障定位
数据库·sql·mysql
还是鼠鼠18 小时前
AI掘金头条新闻系统 (Toutiao News)-缓存相关推荐新闻
后端·python·mysql·fastapi·web