
SELECT
查询的执行顺序
一般来说,在 MySQL 中 SELECT
查询语句的执行顺序如下:
FROM
:指定要从哪个表或多个表中检索数据。WHERE
:对从FROM
子句中获取的数据进行筛选,根据指定的条件过滤出符合条件的行。GROUP BY
:将WHERE
子句筛选后的结果按照指定的列进行分组。HAVING
:对分组后的结果进行筛选,通常用于过滤分组统计后的结果。SELECT
:选择要检索的列和对列进行的计算、函数操作等。ORDER BY
:对查询结果按照指定的列进行排序。
练习题 1
题目:假设有一个名为 students
的表,包含 id
(整数类型,主键)、name
(字符串类型)、age
(整数类型)和 grade
(整数类型)字段。请编写一个查询,找出年龄大于 20 岁且成绩大于 80 分的学生的姓名和年龄。
创建 students
表并插入数据
CREATE TABLE students (
id INT PRIMARY KEY AUTO_INCREMENT,
name VARCHAR(50),
age INT,
grade INT
);
INSERT INTO students (name, age, grade)
VALUES ('Alice', 21, 85),
('Bob', 18, 70),
('Charlie', 22, 90),
('David', 19, 80),
('Eve', 23, 95);
执行语句:
SELECT name, age
FROM students
WHERE age > 20 AND grade > 80;
执行顺序如下:
FROM students
:确定要从students
表中获取数据。WHERE age > 20 AND grade > 80
:对从students
表中获取的数据进行筛选,只保留年龄大于 20 并且成绩大于 80 分的行数据。SELECT name, age
:从筛选后的结果中选择name
和age
列的数据进行输出。
输出结果将是:
| name | age |
|---|---|
| Alice | 21 |
| Charlie | 22 |
| Eve | 23 |
一、筛选顺序的影响
以 WHERE
子句为例,如果它的执行顺序在其他操作(如 GROUP BY
或某些列的计算)之后,那么筛选的依据就不是原始数据,可能导致筛选结果不准确。
例如,如果先对数据进行分组计算,再使用 WHERE
子句基于分组结果进行筛选,与先使用 WHERE
子句对原始数据筛选后再进行分组等其他操作,结果会大不相同。
假设有一个 sales
表,包含 sales_id
、sales_person
、sales_amount
列,数据如下:
| sales_id | sales_person | sales_amount |
|---|---|---|
| 1 | John | 100 |
| 2 | Mary | 200 |
| 3 | John | 150 |
| 4 | Mary | 300 |
如果我们有以下两个查询:
查询 1:先分组计算每个销售人员的销售总额,再筛选出总额大于 200 的销售人员
SELECT sales_person, SUM(sales_amount) AS total_sales
FROM sales
GROUP BY sales_person
HAVING total_sales > 200;
查询 2:先筛选出销售金额大于 100 的记录,再对这些记录按照销售人员进行分组计算销售总额
SELECT sales_person, SUM(sales_amount) AS total_sales
FROM (
SELECT *
FROM sales
WHERE sales_amount > 100
) subquery
GROUP BY sales_person;
对于查询 1,结果为:
| sales_person | total_sales |
|---|---|
| Mary | 500 |
对于查询 2,结果为:
| sales_person | total_sales |
|---|---|
| Mary | 500 |
| John | 150 |
可以看到,由于 WHERE
子句执行的先后顺序不同,导致最终的结果不同。
二、分组和聚合的影响
如果 GROUP BY
子句在错误的阶段执行,可能导致分组不符合预期,进而影响聚合函数(如 SUM
、AVG
、COUNT
等)的结果。
比如有一个 students
表,包含 student_id
、class_id
、grade
列,数据如下:
| student_id | class_id | grade |
|---|---|---|
| 1 | 1 | 80 |
| 2 | 1 | 90 |
| 3 | 2 | 70 |
| 4 | 2 | 80 |
如果我们希望先根据班级分组,再计算每个班级的平均成绩,查询如下:
SELECT class_id, AVG(grade) AS average_grade
FROM students
GROUP BY class_id;
结果为:
| class_id | average_grade |
|---|---|
| 1 | 85 |
| 2 | 75 |
但是,如果 GROUP BY
子句执行顺序错误,先进行了其他操作(如某些条件筛选)后再分组,可能得到不符合预期的分组结果和聚合值。
三、排序顺序的影响
ORDER BY
子句的执行顺序是在查询的最后阶段。如果它在其他操作(如聚合计算、筛选等)之前执行,那么排序的依据就不是最终的查询结果,导致排序结果错误。
例如有一个 products
表,包含 product_id
、product_name
、price
列,数据如下:
| product_id | product_name | price |
|---|---|---|
| 1 | Product 1 | 10 |
| 2 | Product 2 | 20 |
| 3 | Product 3 | 15 |
如果我们有一个查询先对价格进行升序排序,然后取前两条记录:
SELECT *
FROM (
SELECT *
FROM products
ORDER BY price ASC
) subquery
LIMIT 2;
与先筛选出记录,再对结果进行排序的结果会不同。






