解讀SQL中GROUP BY和HAVING子句中使用NULL條件問(wèn)題
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;
查詢結(jié)果為空;實(shí)際數(shù)據(jù)庫(kù)存在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;
問(wèn)題的核心在于 GROUP BY 和 HAVING 子句的工作方式,以及 NULL 的處理規(guī)則
1. HAVING batch IS NULL 沒(méi)有數(shù)據(jù)的原因
當(dāng)你使用 GROUP BY 并在 HAVING 子句中直接使用 batch IS NULL,SQL 會(huì)在分組后的結(jié)果中查找 batch 的值是否為 NULL。但是由于 GROUP BY 會(huì)對(duì)所有同一組內(nèi)的數(shù)據(jù)進(jìn)行聚合,batch 字段可能包含 NULL 和非 NULL 的混合值。
對(duì)于 GROUP BY 而言,它不會(huì)簡(jiǎn)單地保留 batch 字段的某一個(gè)特定值,因此如果某個(gè)分組內(nèi)的 batch 值既有 NULL 又有非 NULL 的情況,batch IS NULL 這個(gè)條件會(huì)失效,因?yàn)?SQL 無(wú)法確定這一組的 batch 值究竟是 NULL 還是非 NULL。
直接使用 HAVING batch IS NULL 通常只能在整個(gè)分組的 batch 全部是 NULL 的情況下才會(huì)生效。
簡(jiǎn)而言之,當(dāng) batch 列在分組后不全是 NULL 時(shí),HAVING batch IS NULL 無(wú)法篩選出結(jié)果。
2. HAVING SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0 結(jié)果正確的原因
SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) 的邏輯是通過(guò) CASE 語(yǔ)句來(lái)計(jì)算某個(gè)分組內(nèi) batch 列為 NULL 的記錄數(shù)。
SUM 是對(duì)整個(gè)分組內(nèi)的每一條記錄進(jìn)行處理,因此即使該組內(nèi)存在 batch 的非 NULL 值,只要有任何一條記錄的 batch 是 NULL,SUM 就能正確計(jì)算出這一組包含 NULL 值的數(shù)量。
解釋:
- SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0:通過(guò)這個(gè) SUM,我們計(jì)算出當(dāng)前分組內(nèi)有多少條記錄的 batch 為 NULL,如果結(jié)果大于 0,說(shuō)明這一組內(nèi)存在 NULL 值的 batch。
- HAVING batch IS NULL:只能篩選出分組后 batch 的值完全為 NULL 的情況,無(wú)法處理那些包含 NULL 和非 NULL 值的分組。
總結(jié)
HAVING batch IS NULL 只能處理整個(gè)分組中的 batch 全為 NULL 的情況,這在有混合值的分組中會(huì)導(dǎo)致結(jié)果為空。
HAVING SUM(CASE WHEN batch IS NULL THEN 1 ELSE 0 END) > 0 可以處理分組中包含 NULL 和非 NULL 的情況,因此它能正確返回包含 NULL 值的分組。
這種 SUM(CASE WHEN…) 邏輯提供了更細(xì)粒度的控制,可以確保即使在分組中存在多個(gè)不同的 batch 值,依然可以正確識(shí)別出那些包含 NULL 的分組。
補(bǔ)充
如果查詢id字段的話 上面的SQL結(jié)果會(huì)發(fā)現(xiàn),id結(jié)果不是我們想要的batch為null的行ID
可改造SQL為下面 執(zhí)行:
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 );
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
為什么MySQL 刪除表數(shù)據(jù) 磁盤(pán)空間還一直被占用
這篇文章主要討論為什么MySQL 刪除表數(shù)據(jù) 磁盤(pán)空間還一直被占用,項(xiàng)目中使用Mysql作為數(shù)據(jù)庫(kù),對(duì)于表來(lái)說(shuō),一般為表結(jié)構(gòu)和表數(shù)據(jù)。表結(jié)構(gòu)占用空間都是比較小的,一般都是表數(shù)據(jù)占用的空間。接下來(lái)小編就和大家一起進(jìn)入下面文章內(nèi)容的學(xué)習(xí)2021-10-10mysql如何實(shí)現(xiàn)多行查詢結(jié)果合并成一行
利用函數(shù):group_concat(),實(shí)現(xiàn)一個(gè)ID對(duì)應(yīng)多個(gè)名稱時(shí),原本為多行數(shù)據(jù),把名稱合并成一行2013-12-12MySQL 使用SQL語(yǔ)句修改表名的實(shí)現(xiàn)
這篇文章主要介紹了MySQL 使用SQL語(yǔ)句修改表名的實(shí)現(xiàn)操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-04-04PostgreSQL 正則表達(dá)式 常用函數(shù)的總結(jié)
這篇文章主要介紹了PostgreSQL 正則表達(dá)式 常用函數(shù)的總結(jié)的相關(guān)資料,對(duì)那些需要進(jìn)行復(fù)雜數(shù)據(jù)處理的程序來(lái)說(shuō),正則表達(dá)式無(wú)疑是一個(gè)非常有用的工具,這里就介紹下如何使用,需要的朋友可以參考下2017-08-08MySQL Lock wait timeout exceeded錯(cuò)誤
“Lock wait timeout exceeded” 是一個(gè)常見(jiàn)的MySQL錯(cuò)誤,指示了潛在的性能問(wèn)題或死鎖,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下2024-05-05MySQL生產(chǎn)庫(kù)Insert了2次同樣的記錄但是主鍵ID是不一樣的問(wèn)題的分析過(guò)程
這篇文章主要介紹了MySQL生產(chǎn)庫(kù)Insert了2次同樣的記錄但是主鍵ID是不一樣的問(wèn)題的分析過(guò)程,需要的朋友可以參考下2014-02-02MySQL數(shù)據(jù)庫(kù)中CAST與CONVERT函數(shù)實(shí)現(xiàn)類型轉(zhuǎn)換的講解
今天小編就為大家分享一篇關(guān)于MySQL數(shù)據(jù)庫(kù)中CAST與CONVERT函數(shù)實(shí)現(xiàn)類型轉(zhuǎn)換的講解,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧2019-03-03