01-SQL 语句的关键字顺序
目录
1. 先有个小表,方便脑补画面
2. 目标:查出“总销售额 > 1000 的销售人员”
3. 执行顺序到底是怎么走的?
3.1 WHERE 到底在干嘛?——“挑行”
3.2 GROUP BY 在干嘛?——“把行捏成组”
3.3 HAVING 在干嘛?——“挑组”
4. 为什么 HAVING 里可以用 SUM(),而 WHERE 里不行?
5. 再用一句特别土但好记的话总结一下
WHERE 针对“行”,在分组前过滤;
HAVING 针对“组”,在 GROUP BY 之后过滤。
拆成两句:
-
WHERE:先从原始表里挑行。
-
HAVING:再从分好组后的“每一组结果”里挑组。
1. 先有个小表,方便脑补画面
假设有一张表 sales(订单表):
| id | seller | amount |
|---|---|---|
| 1 | A | 100 |
| 2 | A | 900 |
| 3 | B | 500 |
| 4 | B | 600 |
| 5 | C | -50 |
含义:
-
seller:销售人员 -
amount:订单金额(有可能是负的,比如退款)
2. 目标:查出“总销售额 > 1000 的销售人员”
我们想写一条 SQL:
找到每个销售
seller的总销售额,
然后只保留“总额 > 1000 的人”。
这时候,一般会这样写:
SELECT seller, SUM(amount) AS total
FROM sales
WHERE amount > 0
GROUP BY seller
HAVING SUM(amount) > 1000
ORDER BY total DESC;
这条 SQL 里就包含了你说的那些关键字:
SELECT + FROM + WHERE + GROUP BY + HAVING + ORDER BY
3. 执行顺序到底是怎么走的?
虽然你是“从上往下写”,
但数据库执行的逻辑顺序大概是这样(简化版):
-
FROM:拿到原始表sales -
WHERE:在 原始行 上进行过滤 -
GROUP BY:把剩下的行按seller分组 -
HAVING:在 每一组 上过滤 -
SELECT:算出你要的列(比如SUM(amount)) -
ORDER BY:对结果排序 -
LIMIT:截取前几条(如果有)
3.1 WHERE 到底在干嘛?——“挑行”
看这一句:
WHERE amount > 0
它的意思就是:
只保留
amount > 0的行,其他行先丢掉。
对我们的 sales 表来说:
原始数据:
| id | seller | amount |
|---|---|---|
| 1 | A | 100 |
| 2 | A | 900 |
| 3 | B | 500 |
| 4 | B | 600 |
| 5 | C | -50 |
经过 WHERE amount > 0 之后,“逐行检查”:
-
行 1:100 > 0 ✅ 留
-
行 2:900 > 0 ✅ 留
-
行 3:500 > 0 ✅ 留
-
行 4:600 > 0 ✅ 留
-
行 5:-50 > 0 ❌ 丢
过滤之后只剩:
| id | seller | amount |
|---|---|---|
| 1 | A | 100 |
| 2 | A | 900 |
| 3 | B | 500 |
| 4 | B | 600 |
这里你注意:还没有分组,只有行。
所以说:WHERE 是“针对行”过滤,在分组之前。
3.2 GROUP BY 在干嘛?——“把行捏成组”
然后来到:
GROUP BY seller
现在把剩下的行按 seller 分组:
-
组 A:行 1(100)、行 2(900)
-
组 B:行 3(500)、行 4(600)
每个组里有好几行,接下来我们就可以对“组”做统计,比如 SUM(amount)。
3.3 HAVING 在干嘛?——“挑组”
HAVING SUM(amount) > 1000
这就不是在看“单独某一行”了,而是在看“一个组的汇总结果”。
-
对 A 组:
-
SUM(amount)= 100 + 900 = 1000 → 不大于 1000 ❌ 丢掉
-
-
对 B 组:
-
SUM(amount)= 500 + 600 = 1100 → > 1000 ✅ 保留
-
所以最后只剩下 B 组(seller = 'B')。
这就解释了那句关键话:
WHERE 针对行,在分组前过滤;
HAVING 针对组,在 GROUP BY 之后过滤。
-
WHERE 看的是:原始表中的每一行
-
HAVING 看的是:每个分组(GROUP BY 后)的统计结果
4. 为什么 HAVING 里可以用 SUM(),而 WHERE 里不行?
试想一下,如果你写:
WHERE SUM(amount) > 1000 -- ❌ 这是错误写法
问题来了:
在分组之前,是没有“组”的概念的,也没有“sum 出来的结果”。
-
WHERE 执行时:只有原始行
→ 它不知道一个组里一共有几行,更没法算总和 -
所以:
-
WHERE 里 不能直接用
SUM(count...)等聚合函数来过滤 -
这些只能放到 HAVING 里,因为 HAVING 是在
GROUP BY之后
-
所以正确写法是:
GROUP BY seller
HAVING SUM(amount) > 1000; -- ✅
5. 再用一句特别土但好记的话总结一下
你可以这么记(非常口语):
-
WHERE:先挑人,再分组。
比如:先把“负数金额的订单”删掉,再按销售分组。 -
HAVING:先分组,再挑组。
比如:按销售分完组,再看哪些销售“总金额 > 1000”,把组扔掉或保留。
或者一口气说出来(面试版):
SQL 的执行顺序大致是:
FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT。其中:
WHERE 在分组前,对行进行过滤;
HAVING 在分组后,对每个组的汇总结果进行过滤;
所以 HAVING 中可以使用SUM/COUNT这样的聚合函数,而 WHERE 不行。
