在 MySQL 中,SQL 查询的执行顺序是非常重要的。
标准 SQL 查询结构
一个典型的 SQL 查询可能包含以下部分:
SELECT [DISTINCT] column1, aggregate_function(column2), ...
FROM table_name
[JOIN other_table ON join_conditions]
[WHERE where_conditions]
[GROUP BY column1, column2, ...]
[HAVING group_conditions]
[ORDER BY column1 [ASC|DESC], column2 [ASC|DESC], ...]
[LIMIT row_count OFFSET offset];
SQL 查询的实际执行顺序
尽管我们书写 SQL 查询时按照上述顺序排列,但 MySQL 实际上会以以下顺序执行这些部分:
1. FROM 和 JOIN
- 作用:确定查询的数据来源(表),并应用
JOIN
操作将多个表组合在一起。 - 执行内容:
- 读取指定的表。
- 如果有
JOIN
,则根据连接条件合并表中的数据。
- 示例:
FROM orders JOIN customers ON orders.customer_id = customers.id
2. WHERE
- 作用:对从
FROM
和JOIN
得到的结果集进行初步过滤。 - 执行内容:
- 只保留满足
WHERE
条件的行。 - 注意:此时不能使用聚合函数,因为分组尚未发生。
- 只保留满足
- 示例:
WHERE orders.status = 'completed'
3. GROUP BY
- 作用:将结果集按指定的列或表达式进行分组。
- 执行内容:
- 将数据划分为多个组,每组具有相同的
GROUP BY
列值。 - 此时可以开始计算聚合函数(如
COUNT()
,SUM()
等)。
- 将数据划分为多个组,每组具有相同的
- 示例:
GROUP BY customers.country
4. 聚合函数计算
- 作用:对每个分组应用聚合函数。
- 执行内容:
- 计算每个分组的聚合值,例如
COUNT(*)
,SUM(order_amount)
等。
- 计算每个分组的聚合值,例如
- 示例:
SELECT customers.country, COUNT(orders.order_id) AS order_count
5. HAVING
- 作用:对分组后的结果进行进一步过滤。
- 执行内容:
- 过滤掉不满足
HAVING
条件的分组。 - 注意:
HAVING
是唯一可以使用聚合函数的过滤条件(不同于WHERE
)。
- 过滤掉不满足
- 示例:
HAVING COUNT(orders.order_id) > 10
6. SELECT
- 作用:选择最终要返回的列或表达式。
- 执行内容:
- 根据
SELECT
子句中指定的列或表达式返回结果。 - 如果使用了
DISTINCT
,则在此步骤去除重复的行。
- 根据
- 示例:
SELECT customers.country, COUNT(orders.order_id) AS order_count
7. ORDER BY
- 作用:对最终结果集进行排序。
- 执行内容:
- 根据指定的列或表达式对结果进行升序(
ASC
)或降序(DESC
)排序。
- 根据指定的列或表达式对结果进行升序(
- 示例:
ORDER BY order_count DESC
8. LIMIT / OFFSET
- 作用:限制返回的行数。
- 执行内容:
LIMIT
用于限制返回的最大行数。OFFSET
用于跳过指定数量的行。
- 示例:
LIMIT 10 OFFSET 0
完整示例
假设有一个订单系统,包含以下两个表:
orders: 存储订单信息。
order_id
: 订单 IDcustomer_id
: 客户 IDstatus
: 订单状态(如 “completed”, “pending”)amount
: 订单金额
customers: 存储客户信息。
customer_id
: 客户 IDcountry
: 客户所在国家
我们需要统计每个国家的已完成订单数量,并仅显示订单数量大于 5 的国家,最后按订单数量降序排列。
SQL 查询
SELECT
customers.country,
COUNT(orders.order_id) AS completed_order_count
FROM
customers
JOIN
orders ON customers.customer_id = orders.customer_id
WHERE
orders.status = 'completed'
GROUP BY
customers.country
HAVING
COUNT(orders.order_id) > 5
ORDER BY
completed_order_count DESC
LIMIT 10;
执行顺序分析
FROM 和 JOIN:
- 从
customers
表和orders
表中读取数据,并通过JOIN
合并它们。
- 从
WHERE:
- 过滤出
orders.status = 'completed'
的记录。
- 过滤出
GROUP BY:
- 按
customers.country
对数据进行分组。
- 按
聚合函数计算:
- 计算每个国家的订单数量
COUNT(orders.order_id)
。
- 计算每个国家的订单数量
HAVING:
- 过滤掉订单数量小于等于 5 的国家。
SELECT:
- 返回
customers.country
和completed_order_count
。
- 返回
ORDER BY:
- 按
completed_order_count
降序排列。
- 按
LIMIT:
- 最多返回 10 条记录。
总结
聚合函数的作用:
- 聚合函数只能在
SELECT
、HAVING
和ORDER BY
子句中使用。 - 在
WHERE
子句中不能直接使用聚合函数,因为此时分组尚未完成。
- 聚合函数只能在
执行顺序的关键点:
- 数据先通过
FROM
和JOIN
获取。 - 然后通过
WHERE
进行初步过滤。 - 接着通过
GROUP BY
分组并计算聚合值。 - 使用
HAVING
对分组结果进行过滤。 - 最后通过
SELECT
、ORDER BY
和LIMIT
输出最终结果。
- 数据先通过
理解 SQL 查询的执行顺序对于优化查询性能以及解决复杂查询问题非常重要!如果还有其他疑问,请随时告诉我!