SQLite中GROUP BY与WHERE子句对NULL的处理差异解析
SQLite中NULL值的分组与筛选逻辑疑问
作为SQL新手,我在尝试隔离第一个查询里的7条NULL行时得到了超出预期的结果。我查阅了SQLite官方文档但仍没搞懂:为什么第一个查询的GROUP BY会把7条NULL行单独分组,而WHERE子句中使用!= ''、not in ('A','H')、=''时却都会排除这些NULL行?看起来NULL好像不在这些判断的范围内,但又能被GROUP BY单独分组,恳请解释这个逻辑。
相关查询及结果如下:
sqlite> select substr(trim(grammarCode),1,1) as c, count(indexRow) as cnt from tbl group by c order by cnt; c cnt - ------ 7 A 4828 20046 H 300679
sqlite> select substr(trim(grammarCode),1,1) as c, count(indexRow) as cnt from tbl where c != '' group by c order by cnt; c cnt - ------ A 4828 H 300679
sqlite> select substr(trim(grammarCode),1,1) as c, count(indexRow) as cnt from tbl where c not in ('A', 'H') group by c order by cnt; c cnt - ------ 20046
sqlite> select substr(trim(grammarCode),1,1) as c, count(indexRow) as cnt from tbl where c = '' group by c order by cnt; c cnt - ------ 20046
sqlite> select substr(trim(grammarCode),1,1) as c, count(indexRow) as cnt from tbl where c is null group by c order by cnt; c cnt - ------ 7
核心逻辑解释
这一切的根源是SQL中NULL的本质是「未知值」,它和任何值的比较规则都和普通值不同:
WHERE子句的过滤规则:WHERE只保留判断结果为「真(TRUE)」的行,而任何和NULL的比较(除了
IS NULL/IS NOT NULL)结果都是「未知(UNKNOWN)」,不属于「真」,所以这些行都会被过滤掉:- 当
c是NULL时,c != ''、c = ''、c not in ('A','H')这些判断的结果都是UNKNOWN,因此包含NULL的行都会被WHERE排除。
- 当
GROUP BY的分组规则:SQL标准规定,所有NULL值会被视为「相等」,所以GROUP BY会把所有
c为NULL的行归为同一个分组,这就是第一个查询里出现cnt=7的NULL分组的原因。
再结合你的查询逐一对应:
- 第一个查询没有WHERE过滤,所以所有行都参与分组:NULL行形成一组(7条),空字符串
''的行形成另一组(20046条),A、H各自成组。 - 用
c != ''过滤时,NULL行和空字符串行都被排除,只剩A、H的分组。 - 用
c not in ('A','H')过滤时,NULL行被排除,只剩空字符串的分组。 - 用
c = ''过滤时,NULL行被排除,只剩空字符串的分组。 - 只有用
c is null时,才能精准匹配到NULL行,得到那7条的分组。
内容的提问来源于stack exchange,提问作者Gary
相关产品推荐
相关产品推荐

