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


相关推荐
August_._3 小时前
【MySQL】SQL语法详细总结
java·数据库·后端·sql·mysql·oracle
stevenzqzq3 小时前
android lambda回调
android
林北北的霸霸5 小时前
django初识与安装
android·mysql·adb
想睡hhh6 小时前
mysql内置函数——了解常用的函数
mysql
Archy_Wang_16 小时前
centos7的mysql做定时任务备份所有数据库
数据库·mysql
Java 码农7 小时前
MySQL EXPLAIN 详解与优化指南
android·mysql·adb
Java 码农7 小时前
MySQL基础操作案例设计
数据库·mysql
csdn_aspnet8 小时前
如何在 Mac、Ubuntu、CentOS、Windows 上安装 MySQL 客户端
linux·windows·mysql·macos·centos
qq_5470261798 小时前
Canal实时同步MySQL数据到Elasticsearch
数据库·mysql·elasticsearch