最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

mysql踩坑之count distinct多列問題

 更新時間:2023年03月23日 08:50:12   作者:山木枝  
這篇文章主要介紹了mysql踩坑之count distinct多列問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教

背景

有個小伙伴在用mysql做統(tǒng)計分析的時候發(fā)現(xiàn)有行數(shù)據(jù)憑空消失了。

最近我剛好在學(xué)習(xí)相關(guān)內(nèi)容,所以對這個問題比較感興趣,就研究了一下。

復(fù)現(xiàn)的測試數(shù)據(jù)庫如下所示:

CREATE TABLE `test_distinct` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `a` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  `b` varchar(50) CHARACTER SET utf8 DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=latin1;

表內(nèi)測試數(shù)據(jù)如下,現(xiàn)在我們需要統(tǒng)計這三列去重后的列的數(shù)量。

問題分析

小伙伴給了我四條用來定位問題的查詢語句

SELECT COUNT(*) AS cnt FROM test_distinct;
SELECT COUNT(DISTINCT id, a, b) as cnt FROM test_distinct;
SELECT id, a, b, COUNT(*) AS cnt FROM test_distinct GROUP BY id, a, b HAVING cnt > 1;
SELECT 
	l.id AS l_id,
	l.a AS l_a,
	l.b AS l_b,
	r.id AS r_id,
	r.a AS r_a,
	r.b AS r_b
FROM test_distinct l LEFT JOIN test_distinct r
ON l.id = r.id AND l.a = r.a AND l.b = r.b
WHERE r.id is NULL or r.id = 'null';

查詢結(jié)果,如下所示:

注意?。?!從測試數(shù)據(jù)很快就能大概猜出問題在哪,但是原來表中數(shù)據(jù)是有3萬多條,無法用肉眼查看數(shù)據(jù)。

上面查詢結(jié)果違反直覺的點有兩個:

  • 第二條去重統(tǒng)計后數(shù)據(jù)少了一條,但是,第三條數(shù)據(jù)的結(jié)果顯示并沒有相同的數(shù)據(jù)。
  • 用同一張表做左外連接出現(xiàn)了驅(qū)動表有數(shù)據(jù),而被驅(qū)動表為空的情況。

先看第二個問題,官方文檔上有如下解釋:

  • 與ON一起使用的search_condition和WHERE子句中使用的條件表達(dá)式一樣。 通常,ON子句用于指定如何連接表的條件,WHERE子句限制要包含在結(jié)果集中的行。
  • 如果對于LEFT JOIN中ON或USING部分中的條件,右表沒有匹配的行,則右表使用所有列設(shè)置為NULL。
  • 不能使用算術(shù)比較運(yùn)算符(如=,<或<>)來比較NULL。
SELECT NULL = NULL;
SELECT NULL IS NULL;

所以問題二在于NULL=NULL的結(jié)果永遠(yuǎn)為False,也就導(dǎo)致兩行原本相等的數(shù)據(jù)結(jié)果卻不相等。

可是這并沒有解決第一個問題:為什么去重后有一條數(shù)據(jù)消失了。但是,我們可以猜測消失的數(shù)據(jù)很有可能和NULL值有關(guān)系。

我們將count和distinct兩個操作分開:

SELECT COUNT(*) as cnt FROM (SELECT  DISTINCT id, a, b FROM test_distinct) as tmp;

嗯?結(jié)果是正確的,那就說明count(distinct expr)生成的查詢計劃可能和我們想象的不一樣,并不是先去重再統(tǒng)計,使用explain分析一下兩條語句的查詢計劃,如下所示:

從表中可以看到,mysql執(zhí)行引擎直接將count(distinct expr)作為一個查詢,查看官方文檔:

解決辦法

至此問題才終于弄清楚了。解決這個問題的辦法有兩種,第一種就是上述的先去重后統(tǒng)計,第二種可以利用IFNULL()函數(shù):

SELECT COUNT(DISTINCT id, a, IFNULL(b, '0')) as cnt FROM test_distinct;

另外補(bǔ)充一點,count()嘚瑟使用:

SELECT id, a, b, COUNT(*) FROM test_distinct GROUP BY id, a, b;
SELECT id, a, b, COUNT(b) FROM test_distinct GROUP BY id, a, b;

知識點

  • 不能使用算術(shù)比較運(yùn)算符(如=,<或<>)來比較空值;
  • count(distinct expr)返回expr列中不同的且非空的行數(shù);
  • COUNT()有兩個非常不同的作用:它可以統(tǒng)計某個列值的數(shù)量,也可以統(tǒng)計行數(shù)。在統(tǒng)計列值時要求列值是非空的(不統(tǒng)計NULL)。如果在COUNT()的括號中定了列或者列表達(dá)式,則統(tǒng)計的就是這個表達(dá)式有值的結(jié)果數(shù)。COUNT()的另一個作用是統(tǒng)計結(jié)果集的行數(shù)。當(dāng)MySQL確認(rèn)括號內(nèi)的表達(dá)式值不可能為空時,實際上就是在統(tǒng)計行數(shù)。最簡單的就是當(dāng)我們使用COUNT()的時候,這種情況下通配符并不像我們猜想的那樣擴(kuò)展成所有的列,實際上,他會忽略所有列而直接統(tǒng)計所有的行數(shù)——《高性能MySQL》;
  • 在InnoDB中,SELECT COUNT(*)和SELECT COUNT(1)處理方式一樣, 沒有性能差異。

總結(jié)

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • MySql like模糊查詢通配符使用詳細(xì)介紹

    MySql like模糊查詢通配符使用詳細(xì)介紹

    MySQL提供標(biāo)準(zhǔn)的SQL模式匹配,以及一種基于象Unix實用程序如vi、grep和sed的擴(kuò)展正則表達(dá)式模式匹配的格式
    2013-10-10
  • Mysql使用函數(shù)后不走索引怎么優(yōu)化

    Mysql使用函數(shù)后不走索引怎么優(yōu)化

    當(dāng)在MySQL中使用函數(shù)時,可能會導(dǎo)致查詢不走索引,從而影響性能,本文就介紹一下Mysql使用函數(shù)后不走索引怎么優(yōu)化,感興趣的可以了解一下
    2023-08-08
  • InnoDB引擎中的事務(wù)詳解

    InnoDB引擎中的事務(wù)詳解

    這篇文章主要介紹了InnoDB引擎中的事務(wù)詳解,事務(wù)Transaction是訪問和更新數(shù)據(jù)庫的程序執(zhí)行單元;事務(wù)中可能包含一個或多個sql語句,這些語句要么都執(zhí)行,要么都不執(zhí)行,需要的朋友可以參考下
    2023-09-09
  • MySQL系列之六 用戶與授權(quán)

    MySQL系列之六 用戶與授權(quán)

    做為Mysql數(shù)據(jù)庫管理員管理用戶賬戶,是一件很重要的事,指出哪個用戶可以連接服務(wù)器,從哪里連接,連接后能做什么,這篇文章主要介紹了MySQL用戶與授權(quán)的相關(guān)資料,需要的朋友可以參考下
    2021-07-07
  • MySQL全量備份的實現(xiàn)

    MySQL全量備份的實現(xiàn)

    全量備份是MySQL數(shù)據(jù)庫備份的常見方式,本文主要介紹了MySQL全量備份的實現(xiàn),全量備份和增量備份是 MySQL 數(shù)據(jù)庫備份的兩種常見方式
    2024-04-04
  • 簡單實現(xiàn)SQLServer轉(zhuǎn)MYSQL的方法

    簡單實現(xiàn)SQLServer轉(zhuǎn)MYSQL的方法

    SqlServer數(shù)據(jù)轉(zhuǎn)換成mysql數(shù)據(jù),可以說是一個老生常談了,網(wǎng)上也有很多的方法,今天我們來看一種不一樣的方法,而且也非常的簡單,雖然有點小缺陷,但還是不失為一種很好的方法,當(dāng)然如果結(jié)合mss2sql那就非常完美了
    2014-08-08
  • Linux系統(tǒng)利用crontab定時備份Mysql數(shù)據(jù)庫方法

    Linux系統(tǒng)利用crontab定時備份Mysql數(shù)據(jù)庫方法

    本文教你如果快速利用系統(tǒng)crontab來定時執(zhí)行備份文件,按日期對備份結(jié)果進(jìn)行保存
    2021-09-09
  • MySql連接數(shù)據(jù)庫常用參數(shù)及代碼解讀

    MySql連接數(shù)據(jù)庫常用參數(shù)及代碼解讀

    這篇文章主要介紹了MySql連接數(shù)據(jù)庫常用參數(shù)及代碼解讀,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-02-02
  • MySQL 獨立索引和聯(lián)合索引的選擇

    MySQL 獨立索引和聯(lián)合索引的選擇

    為了提高數(shù)據(jù)庫效率,建索引是家常便飯;那么當(dāng)查詢條件為2個及以上時,我們是創(chuàng)建多個單列索引還是創(chuàng)建一個聯(lián)合索引好呢?他們之間的區(qū)別是什么?哪個效率高呢?本文將詳細(xì)測試分析下。
    2021-05-05
  • MySQL5.7.18修改密碼的方法

    MySQL5.7.18修改密碼的方法

    這篇文章主要介紹了MySQL5.7.18修改密碼的方法,非常不錯,具有參考解決價值,需要的朋友可以參考下
    2017-05-05

最新評論

焦作市| 长海县| 贵溪市| 庆阳市| 天台县| 舟曲县| 洛川县| 蓬莱市| 荔波县| 新津县| 青岛市| 佛学| 裕民县| 句容市| 彰化县| 墨竹工卡县| 张家口市| 云龙县| 金华市| 龙陵县| 方城县| 渝北区| 南和县| 金门县| 阳原县| 宜章县| 昌吉市| 凯里市| 大安市| 巨野县| 洪江市| 新民市| 荆门市| 广灵县| 盘锦市| 玉林市| 子洲县| 临西县| 东阳市| 海淀区| 吉林市|