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

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)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

睿思达DBA_WGX

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值