You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SQLite中HAVING子句工作原理及等效查询结果疑问

SQLite中HAVING子句的工作原理及查询结果一致性解析

一、你的第一个查询:巧合下的“正确”结果

HAVING子句的核心作用是过滤分组后的结果,它只能用在GROUP BY之后,并且可以搭配聚合函数(比如MAX()、SUM())——这是它和WHERE的最大区别,WHERE是过滤原始行,不能用聚合函数。

你写的HAVING max(salary)其实是个“无效过滤”:在SQLite里,非零数值会被判定为TRUE,零或NULL才是FALSE。你的数据里每个部门的最高薪资都是正数,所以这个条件对所有分组都成立,相当于没加HAVING子句。

那为什么它能返回每个部门薪资最高的人?这是SQLite的非标准扩展行为+数据顺序巧合导致的:
标准SQL要求,SELECT里的列要么在GROUP BY里,要么是聚合函数,但SQLite允许这种写法,此时它会返回分组里的某一行。你的数据里,每个部门的最高薪资恰好是分组里的最后一条记录(比如computer部门最后一条是Bravo的600),而SQLite默认返回分组的最后一行,所以刚好和第二个查询结果一致。

你可以测试一下,把computer部门的两行顺序调换:

CREATE TABLE salaries AS
  SELECT 'Bravo', 'computer', 600 UNION
  SELECT 'Alpha' as name, 'computer' as division, 500 as salary UNION
  SELECT 'Charlie', 'accounting', 200 UNION
  SELECT 'Delta', 'accounting', 300 UNION
  SELECT 'Echo', 'management', 800 UNION
  SELECT 'Foxtrot', 'management', 900;

再运行第一个查询,返回的computer部门人员会是Alpha(薪资500),而不是最高薪的Bravo——这就暴露了第一个查询的不可靠性。

二、第二个查询:标准且稳定的写法

第二个查询是符合SQL标准的关联子查询,逻辑非常清晰:

  1. 外层查询遍历salaries表的每一行
  2. 内层子查询针对当前行的部门,找出该部门的最高薪资
  3. 外层只保留薪资等于对应部门最高薪的行

这个写法不依赖任何数据库的非标准行为,不管数据顺序怎么变,都能准确返回每个部门薪资最高的人员,结果是稳定可靠的。

总结

  • 第一个查询的“正确结果”是巧合,HAVING子句在这里根本没起到过滤作用,而且写法不符合SQL标准,不能保证结果稳定。
  • 第二个查询是获取各部门最高薪人员的标准写法,推荐使用。

内容的提问来源于stack exchange,提问作者Srihari P

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 18:52:39