解读SQL中GROUP BY和HAVING子句中使用NULL条件问题

 更新时间:2024年10月16日 16:23:05   作者:qianer0_0  
在使用SQL进行数据查询时,可能会遇到查询结果为空的情况,这通常与GROUP BY和HAVING子句的使用有关,尤其是在处理包含NULL值的字段时,当使用GROUP BY进行数据分组,并在HAVING子句中直接判断字段是否为NULL时

SQL中GROUP BY和HAVING子句中使用NULL条件

  • SQL :
SELECT COUNT(1), tid, sap_do, batch, skucode,batch 
FROM lt 
WHERE IFNULL(sap_do, '') != '' 
AND created_time >= 1722441600 
GROUP BY tid, sap_do, skucode 
HAVING COUNT(1) > 1 
AND batch IS NULL; 

查询结果为空;实际数据库存在batch IS NULL的

  • 修改后:
SELECT COUNT(1), tid, sap_do, skucode, batch 
FROM lt 
WHERE IFNULL(sap_do, '') != '' 
AND created_time >= 1722441600 
GROUP BY tid, sap_do, skucode 
HAVING COUNT(1) > 1 
AND SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0;

问题的核心在于 GROUP BY 和 HAVING 子句的工作方式,以及 NULL 的处理规则

1. HAVING batch IS NULL 没有数据的原因

当你使用 GROUP BY 并在 HAVING 子句中直接使用 batch IS NULL,SQL 会在分组后的结果中查找 batch 的值是否为 NULL。但是由于 GROUP BY 会对所有同一组内的数据进行聚合,batch 字段可能包含 NULL 和非 NULL 的混合值。

对于 GROUP BY 而言,它不会简单地保留 batch 字段的某一个特定值,因此如果某个分组内的 batch 值既有 NULL 又有非 NULL 的情况,batch IS NULL 这个条件会失效,因为 SQL 无法确定这一组的 batch 值究竟是 NULL 还是非 NULL。

直接使用 HAVING batch IS NULL 通常只能在整个分组的 batch 全部是 NULL 的情况下才会生效。

简而言之,当 batch 列在分组后不全是 NULL 时,HAVING batch IS NULL 无法筛选出结果。

2. HAVING SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0 结果正确的原因

SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) 的逻辑是通过 CASE 语句来计算某个分组内 batch 列为 NULL 的记录数。

SUM 是对整个分组内的每一条记录进行处理,因此即使该组内存在 batch 的非 NULL 值,只要有任何一条记录的 batch 是 NULL,SUM 就能正确计算出这一组包含 NULL 值的数量。

解释:

  • SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0:通过这个 SUM,我们计算出当前分组内有多少条记录的 batch 为 NULL,如果结果大于 0,说明这一组内存在 NULL 值的 batch。
  • HAVING batch IS NULL:只能筛选出分组后 batch 的值完全为 NULL 的情况,无法处理那些包含 NULL 和非 NULL 值的分组。

总结

HAVING batch IS NULL 只能处理整个分组中的 batch 全为 NULL 的情况,这在有混合值的分组中会导致结果为空。

HAVING SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0 可以处理分组中包含 NULL 和非 NULL 的情况,因此它能正确返回包含 NULL 值的分组。

这种 SUM(CASE WHEN…) 逻辑提供了更细粒度的控制,可以确保即使在分组中存在多个不同的 batch 值,依然可以正确识别出那些包含 NULL 的分组。

补充

如果查询id字段的话 上面的SQL结果会发现,id结果不是我们想要的batch为null的行ID

可改造SQL为下面 执行:

SELECT id, tid, sap_do, skucode, batch 
FROM lt
WHERE batch IS NULL
AND (tid, sap_do, skucode) IN (
    SELECT tid, sap_do, skucode
    FROM lt 
    WHERE IFNULL(sap_do, '') != ''
    AND created_time >= 1725120000
    GROUP BY tid, sap_do, skucode
    HAVING COUNT(1) > 1
    AND SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0
);

以上为个人经验,希望能给大家一个参考,也希望大家多多支持脚本之家。

相关文章

  • RR与RC隔离级别下索引和锁的测试脚本示例代码

    RR与RC隔离级别下索引和锁的测试脚本示例代码

    这篇文章主要给大家介绍了关于RR与RC隔离级别下索引和锁的测试脚本的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2018-12-12
  • MySQL5.5 部署的一个问题

    MySQL5.5 部署的一个问题

    这篇文章主要介绍了MySQL5.5部署的一个问题,以及解决方案,帮助大家更好的理解和使用数据库,感兴趣的朋友可以了解下
    2020-11-11
  • mysql8.0.11客户端无法登陆的解决方法

    mysql8.0.11客户端无法登陆的解决方法

    这篇文章主要为大家详细介绍了mysql8.0.11客户端无法登陆的解决方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-05-05
  • mysql 导入导出数据库、数据表的方法

    mysql 导入导出数据库、数据表的方法

    这篇文章主要介绍了mysql 导入导出数据库、数据表的方法,有需要的朋友可以参考一下
    2013-11-11
  • MySql/Oracle数据库项目改造适配信创国产数据库的方法详解

    MySql/Oracle数据库项目改造适配信创国产数据库的方法详解

    项目里用了MySQL数据库,现在要换成国产信创数据库,很多团队都在头疼这个问题,这篇文章主要介绍了MySql/Oracle数据库项目改造适配信创国产数据库的相关资料,文中介绍的非常详细,需要的朋友可以参考下
    2025-11-11
  • MySQL精准控制Binlog日志数量的三种方案

    MySQL精准控制Binlog日志数量的三种方案

    作为数据库管理员,你是否经常为服务器磁盘爆满而抓狂?Binlog就像数据库的“黑匣子”,默默记录着每一次数据变动,但若放任不管,几天内这些日志文件就能吞噬上百GB空间!今天教你三招精准控制Binlog数量,从此告别空间焦虑,需要的朋友可以参考下
    2025-05-05
  • MYSQL数据库管理之权限管理解读

    MYSQL数据库管理之权限管理解读

    这篇文章主要介绍了MYSQL数据库管理之权限管理解读,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2023-03-03
  • MySQL5绿色版windows下安装总结(推荐)

    MySQL5绿色版windows下安装总结(推荐)

    这篇文章主要介绍了MySQL5绿色版windows下安装总结,需要的朋友可以参考下
    2017-03-03
  • MySQL低权限提权的方法

    MySQL低权限提权的方法

    在MySQL中,低权限提权是一种常见的需求,低权限用户通过利用漏洞、存储过程、用户定义函数(UDF)和触发器(Trigger)等技术手段进行权限提升,本文就来介绍一下,感兴趣的可以了解一下
    2024-09-09
  • Mysql5.7忘记root密码怎么办(简单且有效方法)

    Mysql5.7忘记root密码怎么办(简单且有效方法)

    本文给大家分享一个快速且简单的方法来解决Mysql5.7忘记root密码问题,非常不错,具有参考借鉴价值,需要的朋友参考下吧
    2017-02-02

最新评论