MySQL讲义第 32 讲——select 查询之 select 语句的执行顺序

it2025-05-19  10

MySQL讲义第 32 讲——select 查询之 select 语句的执行顺序

SELECT 语句中各个子句的执行顺序与 SELECT 语句中子句的语法顺序是不一样的。

一、SELECT 语句的语法顺序

SELECT 语句在书写时各个关键字要保持下面的顺序:

select [distinct] 字段或表达式列表 from 表名 join(left join, right join) on 连接条件 where 筛选条件 group by 字段列表 having 字段列表 order by 字段列表 limit <m,n>

二、SELECT 语句的执行顺序

SELECT 语句中各个子句按照下面的顺序执行。每个子句执行后都会产生一个中间结果,供接下来的子句使用,如果不存在某个子句,就跳过该子句。

1. FROM子句 2. WHERE子句 3. GROUP BY子句 4. HAVING子句 5. SELECT子句 6. ORDER BY子句 7. LIMIT子句 /* ######################################################################################## 执行顺序的说明: (1) from 子句组装来自不同数据源的数据; (2) where 子句基于指定的条件对记录行进行筛选; (3) group by 子句将数据划分为多个分组; (4) 使用聚集函数进行计算; (5) 使用 having 子句筛选分组; (6) 计算所有的表达式; (7) select 字段; (8) 使用 order by 对结果集进行排序。 关于字段别名的使用: (1) WHERE子句不能使用字段别名。 (2) 从 GROUP BY 子句开始,后面的所有子句可以使用字段别名。 ######################################################################################## */

三、执行过程模拟

后面的查询用到下面的两张表,表结构和数据如下:

mysql> select * from dept; +---------+-----------+ | dept_id | dept_name | +---------+-----------+ | 11 | 财务部 | | 12 | 技术部 | | 13 | 销售部 | | 14 | 公关部 | +---------+-----------+ 4 rows in set (0.00 sec) mysql> select * from emp; +------+-----------+--------+----------+---------+ | e_id | e_name | gender | salary | dept_id | +------+-----------+--------+----------+---------+ | 1101 | 张美华 || 5000.00 | 11 | | 1102 | 王涛 || 5200.00 | 11 | | 1103 | 张学有 || 4700.00 | 11 | | 1201 | 刘得华 || 5200.00 | 12 | | 1202 | 董雯花 || 5900.00 | 12 | | 1203 | 宋族营 || 6500.00 | 12 | | 1204 | 李霜江 || 7200.00 | 12 | | 1301 | 梁美丽 || 7040.00 | 13 | | 1302 | 王大强 || 6710.00 | 13 | | 1303 | 张美华 || 8580.00 | 13 | | 1304 | 赵紫龙 || 7590.00 | 13 | | 1305 | 诸葛量 || 10120.00 | 13 | | 1306 | 曹梦德 || 9240.00 | 13 | +------+-----------+--------+----------+---------+ 13 rows in set (0.00 sec)

1、使用 FROM 子句指定要查询的表,根据 select <字段列表>,得到一个中间表 vt1

mysql> SELECT -> e.e_id, -> e.e_name ename, --为 e_name 指定别名 ename -> e.salary, -> e.dept_id, -> d.dept_name -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id; +------+-----------+----------+---------+-----------+ | e_id | ename | salary | dept_id | dept_name | +------+-----------+----------+---------+-----------+ | 1101 | 张美华 | 5000.00 | 11 | 财务部 | | 1102 | 王涛 | 5200.00 | 11 | 财务部 | | 1103 | 张学有 | 4700.00 | 11 | 财务部 | | 1201 | 刘得华 | 5200.00 | 12 | 技术部 | | 1202 | 董雯花 | 5900.00 | 12 | 技术部 | | 1203 | 宋族营 | 6500.00 | 12 | 技术部 | | 1204 | 李霜江 | 7200.00 | 12 | 技术部 | | 1301 | 梁美丽 | 7040.00 | 13 | 销售部 | | 1302 | 王大强 | 6710.00 | 13 | 销售部 | | 1303 | 张美华 | 8580.00 | 13 | 销售部 | | 1304 | 赵紫龙 | 7590.00 | 13 | 销售部 | | 1305 | 诸葛量 | 10120.00 | 13 | 销售部 | | 1306 | 曹梦德 | 9240.00 | 13 | 销售部 | +------+-----------+----------+---------+-----------+ 13 rows in set (0.00 sec)

2、使用 WHERE 子句对中间表 vt1 进行筛选,得到中间表 vt2

注意:在 WHERE 子句中不能使用字段别名。

mysql> SELECT -> e.e_id, -> e.e_name ename, -> e.salary, -> e.dept_id, -> d.dept_name -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE ename like '王%'; ERROR 1054 (42S22): Unknown column 'ename' in 'where clause' ---说明:出现错误!在 WHERE 子句中不能使用字段别名 ename。 mysql> SELECT -> e.e_id, -> e.e_name ename, -> e.salary, -> e.dept_id, -> d.dept_name -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE -> salary BETWEEN 5000 AND 10000; +------+-----------+---------+---------+-----------+ | e_id | ename | salary | dept_id | dept_name | +------+-----------+---------+---------+-----------+ | 1101 | 张美华 | 5000.00 | 11 | 财务部 | | 1102 | 王涛 | 5200.00 | 11 | 财务部 | | 1201 | 刘得华 | 5200.00 | 12 | 技术部 | | 1202 | 董雯花 | 5900.00 | 12 | 技术部 | | 1203 | 宋族营 | 6500.00 | 12 | 技术部 | | 1204 | 李霜江 | 7200.00 | 12 | 技术部 | | 1301 | 梁美丽 | 7040.00 | 13 | 销售部 | | 1302 | 王大强 | 6710.00 | 13 | 销售部 | | 1303 | 张美华 | 8580.00 | 13 | 销售部 | | 1304 | 赵紫龙 | 7590.00 | 13 | 销售部 | | 1306 | 曹梦德 | 9240.00 | 13 | 销售部 | +------+-----------+---------+---------+-----------+ 11 rows in set (0.00 sec)

3、对中间表 vt2 按照 dept_name 字段分组,统计每个部门的平均工资,得到中间表 vt3

mysql> SELECT -> d.dept_name, -> avg(salary) AS avg_salary -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE -> salary BETWEEN 5000 AND 10000 -> GROUP BY -> d.dept_name; +-----------+-------------+ | dept_name | avg_salary | +-----------+-------------+ | 技术部 | 6200.000000 | | 财务部 | 5100.000000 | | 销售部 | 7832.000000 | +-----------+-------------+ 3 rows in set (0.00 sec)

4、使用 HAVING 子句对中间表 vt3 进行筛选,得到中间表 vt4

mysql> SELECT -> d.dept_name, -> avg(salary) AS avg_salary -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE -> salary BETWEEN 5000 AND 10000 -> GROUP BY -> d.dept_name -> HAVING -> avg_salary > 6000; ---此处使用了表达式别名 +-----------+-------------+ | dept_name | avg_salary | +-----------+-------------+ | 技术部 | 6200.000000 | | 销售部 | 7832.000000 | +-----------+-------------+ 2 rows in set (0.01 sec)

5、使用 ORDER BY 子句对中间表 vt4 进行排序,得到中间表 vt5

mysql> SELECT -> d.dept_name, -> avg(salary) AS avg_salary -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE -> salary BETWEEN 5000 AND 10000 -> GROUP BY -> d.dept_name -> HAVING -> avg_salary > 6000 -> ORDER BY -> avg_salary DESC; +-----------+-------------+ | dept_name | avg_salary | +-----------+-------------+ | 销售部 | 7832.000000 | | 技术部 | 6200.000000 | +-----------+-------------+ 2 rows in set (0.00 sec)

6、使用 LIMIT 子句从中间表 vt5 中取出第一条记录,得到最终的结果表

mysql> SELECT -> d.dept_name, -> avg(salary) AS avg_salary -> FROM -> emp e JOIN dept d ON e.dept_id = d.dept_id -> WHERE -> salary BETWEEN 5000 AND 10000 -> GROUP BY -> d.dept_name -> HAVING -> avg_salary > 6000 -> ORDER BY -> avg_salary DESC -> LIMIT -> 1; +-----------+-------------+ | dept_name | avg_salary | +-----------+-------------+ | 销售部 | 7832.000000 | +-----------+-------------+ 1 row in set (0.00 sec)
最新回复(0)