SQL聚合函数在SELECT与HAVING中的使用规则问询
SQL聚合函数使用规则与SELECT子句执行时机解析
一、聚合函数在SELECT和HAVING中的使用规则
HAVING的核心作用是过滤分组后的结果集,它只能基于分组字段(GROUP BY中指定的字段)或聚合函数设定条件;而SELECT中的聚合函数,本质是定义最终要输出的聚合计算结果列,属于结果展示环节。
举两个实际例子对比:
- 仅在SELECT中使用聚合函数:
SELECT department, COUNT(*) AS employee_count FROM employees GROUP BY department;
这会返回所有部门的员工数量,不管每个部门人数多少。
- 同时在SELECT和HAVING中使用聚合函数:
SELECT department, COUNT(*) AS employee_count FROM employees GROUP BY department HAVING COUNT(*) >= 10;
这只会返回员工数量≥10的部门,结果和第一个查询明显不同。
关键规则:
- SELECT里的聚合函数:用来生成最终展示的聚合统计值,可给列设置别名方便后续引用(但仅在ORDER BY等后续步骤生效)。
- HAVING里的聚合函数:用来筛选分组,只有满足聚合条件的分组才会进入最终结果集;注意HAVING不能直接使用SELECT中定义的列别名,因为执行顺序上HAVING先于SELECT。
二、SELECT子句的实际执行时机
你对SELECT“按指定格式展示列”的理解没错,但SQL的执行顺序并不是从SELECT开始的,实际执行流程大致是:
- FROM:确定查询的数据源(表、视图等)
- WHERE:逐行过滤原始数据(此时还未分组,不能使用聚合函数)
- GROUP BY:将过滤后的行按指定字段分组
- HAVING:过滤分组后的结果集(可使用聚合函数)
- SELECT:选择要展示的列(包括分组字段、聚合计算结果,此时可设置列别名)
- ORDER BY:对最终结果排序(可使用SELECT中设置的别名)
正是因为HAVING执行在SELECT之前,所以HAVING里无法识别SELECT定义的别名,必须直接写聚合函数或分组字段。
三、你的实验结果相同的原因
你两次查询结果一致,大概率是因为添加的HAVING条件没有排除任何分组。比如你用了HAVING COUNT(*) = COUNT(*)这种恒成立的条件,或者HAVING SUM(salary) > 0但所有分组都满足这个条件,所以最终结果和仅在SELECT使用聚合函数的情况没有差异。换一个有实际筛选效果的HAVING条件(比如HAVING COUNT(*) > 5),就能看到明显的结果区别。
内容的提问来源于stack exchange,提问作者Dan
相关产品推荐
相关产品推荐

