记录一个奇怪的现象(SQL 的执行顺序)
SQL 的一般逻辑执行顺序是:
1. FROM 和 JOIN
首先从 FROM 和 JOIN 中的表中选取数据。
2. WHERE
然后应用 WHERE 进行过滤。
3. GROUP BY
接着进行 GROUP BY 分组。
4. HAVING
HAVING 会再基于 GROUP BY 的结果进行过滤。
5. SELECT
然后执行 SELECT 选择需要的列。
> 如果在 `SELECT` 子句中使用了聚合函数,如 `SUM()` 或 `AVG()`,那么这些函数会在这个步骤中被应用于由 `GROUP BY` 子句定义的每个分组。
6. DISTINCT
会排除重复列。
7. ORDER BY
最后是 ORDER BY 排序。
所以一个典型的 SQL 查询执行顺序是:
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> DISTINCT -> ORDER BY
简单总结:
- FROM 和 JOIN 获得原始数据
- WHERE 初步过滤
- GROUP BY 分组
- HAVING 过滤分组
- SELECT 选择列
- DISTINCT 去重
- ORDER BY 排序
当然,数据库查询优化器会根据查询计划调整具体的执行顺序,但这个顺序表达了 SQL 各子句的逻辑关系。
---
记录一个奇怪的现象:
```mysql
select
EventName name,
sum(Duration) total_duration
from events
where EventName = '事件1'
group by name;
```
以上查询语句是对的,把 group by 的 name 换成原字段名 EventName 也是对的,在 DataGrip 中不会报错,也能正常运行。

如果是这样,那上图注释中的第一条论断就不准确了,也与 SQL 的一般执行顺序冲突。
我先后问了 Claude、GPT3.5、GPT4,首次得到的答案都说是 group by 在 select 之前执行!!!
当我拿着以上反例质疑时,Claude 马上承认了 “错误”,并表示学到了新知识,做出了 “改正”,而 GPT3.5 和 GPT4 虽然承认了 “错误”,但在新的答案中却没有 “改正”,一副知错不改的模样。
综合以上信息,再结合我自己的逻辑推断,它们第一次的答案很可能是对的,group by 就是在 select 之前执行!而在这个例子中 group by 之所以能应用 select 的别名 name,很可能是 DataGrip 或 SQL 的容错或优化,与实际执行顺序没有太大的关系。
或许不能简单的根据是否能应用别名来判断执行顺序。
