SQL 聚合终于变得易懂:GROUP BY、HAVING、MIN、MAX、AVG
Source: Dev.to
思维转变:从行到组
到目前为止,我的大多数 SQL 查询都像这样:
“显示满足 X 条件的行”
但 GROUP BY 改变了游戏规则。你不再只考虑行,而是开始考虑行的组。这是一开始最不舒服的部分,所以让我展示一下我的做法。
我今天练习的内容
我处理的查询会提出以下问题:
- 每个国家有多少用户?
- 每个部门的平均工资是多少?
- 哪个部门的平均分最高?
所有这些查询都需要分组——而不是简单的“获取满足条件的行”。
GROUP BY(终于点通了)
一开始,我不断收到类似的错误:
column must appear in the GROUP BY clause or be used in an aggregate function
这个错误信息让我很烦恼……直到我开始多思考并尝试更好地理解这条信息和任务。
帮助我的方法:
如果一个列没有出现在聚合函数中,它必须出现在 GROUP BY 中。
SELECT country, COUNT(*)
FROM users
GROUP BY country;
country→ 用于分组COUNT(*)→ 对每个组进行汇总
但下面这种写法不行:
SELECT country, email
FROM users
GROUP BY country;
因为 SQL 现在在问:“每个国家你想让我挑选哪一个 email?”
这就是我第一次真正的“好吧…合理”的时刻。
MIN、MAX 和 AVG(直接但强大)
当分组概念清晰后,这些函数就显得更自然了。
MIN
SELECT department, MIN(salary)
FROM employees
GROUP BY department;
每个部门的最低工资
MAX
SELECT department, MAX(salary)
FROM employees
GROUP BY department;
每个部门的最高工资
AVG
SELECT department, AVG(salary)
FROM employees
GROUP BY department;
每个部门的平均工资
看到每个组都有实际数值输出,SQL 变得更贴近真实业务。
HAVING(我最初把它和 WHERE 混淆了)
一开始,我写的查询像这样:
SELECT department, AVG(salary)
FROM employees
WHERE AVG(salary) > 50000
GROUP BY department;
SQL 基本上直接说不行。
最终让人记住的区别
WHERE在分组之前过滤行。HAVING在分组之后过滤组。
正确的写法:
SELECT department, AVG(salary)
FROM employees
GROUP BY department
HAVING AVG(salary) > 50000;
一旦把 HAVING 看作是“针对分组数据的 WHERE”,它就不再神秘。
执行顺序
了解执行顺序后,一切都清晰了:
FROMWHERE– 过滤行GROUP BY– 创建组HAVING– 过滤组SELECTORDER BY
这解释了为什么会有 HAVING;WHERE 只是执行得太早了。
仍然感觉怪异的地方
我仍在适应:
- 用组而不是行来思考
- 确定何时真的需要
GROUP BY - 阅读分组查询时不迷失
但与昨天相比?已经是进步了。
我为何分享这些
GROUP BY 和 HAVING 往往被快速教授,例如:
“这里是语法,继续往下走。”
对于初学者来说,这是一种思维转变,而不仅仅是语法。如果你也在学习 SQL,起初对 GROUP BY 感到困惑,你并不孤单。
接下来
我正在慢慢、踏实、诚实地学习 SQL,并记录整个过程,以免其他初学者觉得自己是唯一在挣扎的人。如果你走在同一条路上,你并没有落后——你只是在以正确的方式学习。