MySQL去重中distinct和group by的區別淺析
今天在寫業務需要對數據庫重復字段進行去重時,因為是去重,首先想到的是distinct關鍵字。於是一小時過去瞭。。。。(菜鳥一個,大傢輕點罵)
我把問題的過程用sql語句演示給大傢演示一下
首先我使用的是mybatis-plus,代碼如下
QueryWrapper<ProjectCompany> wrapper = new QueryWrapper<>(); wrapper.select("DISTINCT project_id,company_id,company_name,is_delete").eq("project_id",projectId).eq("is_delete","0");
即 "DISTINCT project_id,company_id,company_name,is_delete"
查出的結果
id=null。這是我不希望看到的。沒有id的話,下面的業務就不好走瞭。
於是我在distinct後面加上瞭id,distinct查出來的數據就是全部數據瞭,相當於distinct沒起作用。冥思苦想一小時。。。。
後來想到瞭group by分組,於是用瞭一下
LambdaQueryWrapper<ProjectCompany> wrapper = new LambdaQueryWrapper<>(); wrapper.eq(ProjectCompany::getProjectId,projectId).eq(ProjectCompany::getIsDelete,"0").groupBy(ProjectCompany::getProjectId);
發現查出來的數據也進行去重瞭,id也有值
所以就很好奇 distinct和group by有啥區別,大概總結以下幾點:
distinct適合查單個字段去重,支持單列、多列的去重方式。 單列去重的方式簡明易懂,即相同值隻保留1個。
多列的去重則是根據指定的去重的列信息來進行,即隻有所有指定的列信息都相同,才會被認為是重復的信息。
而 group by 可以針對要查詢的全部字段中的部分字段去重,它的作用主要是:獲取數據表中以分組字段為依據的其他統計數據。
補充:MySQL中distinct和group by去重性能對比
前言
- MySQL:5.7.17
- 存儲引擎:InnoDB
- 實驗目的:本文主要測試在某字段有無索引、各種不同值個數情況下,記錄對此字段其使用
DISTINCT/GROUP BY
去重的查詢語句執行時間,對比兩者在不同場景下的去重性能,實驗過程中關閉MySQL查詢緩存。 - 實驗表格:
表名 | 記錄數 | 查詢字段有無索引 | 查詢字段不同值個數 | DISTINCT | GROUP BY |
---|---|---|---|---|---|
tab_1 | 100000 | N | 3 | ||
tab_2 | 100000 | Y | 3 | ||
tab_3 | 100000 | N | 10000 | ||
tab_4 | 100000 | Y | 10000 |
實驗過程
1)創建測試表
表創建語句:
DROP TABLE IF EXISTS `tab_1`; CREATE TABLE `tab_1` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `value` int(10) unsigned NOT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `tab_2`; CREATE TABLE `tab_2` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT, `value` int(10) unsigned NOT NULL, PRIMARY KEY (`id`), KEY `idx_value` (`value`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; DROP TABLE IF EXISTS `tab_3`; CREATE TABLE `tab_3` LIKE `tab_1`; DROP TABLE IF EXISTS `tab_4`; CREATE TABLE `tab_4` LIKE `tab_2`;
2)生成測試數據
表數據插入過程:
DROP PROCEDURE IF EXISTS generateRandomData; delimiter $$ -- tblName為插入表,field為插入字段,num為插入字段值上限,count為插入的記錄數 CREATE PROCEDURE generateRandomData(IN tblName VARCHAR(30),IN field VARCHAR(30),IN num INT UNSIGNED,IN count INT UNSIGNED) BEGIN -- 聲明循環變量 DECLARE i INT UNSIGNED DEFAULT 1; -- 循環插入隨機整數1~num,共插入count條數據 w1:WHILE i<=count DO set i=i+1; set @val = FLOOR(RAND()*num+1); set @statement = CONCAT('INSERT INTO ',tblName,'(`',field,'`) VALUES(',@val,')'); PREPARE stmt FROM @statement; EXECUTE stmt; END WHILE w1; END $$ delimiter ;
調用過程隨機生成測試數據:
call generateRandomData('tab_1','value',3,100000); INSERT INTO tab_2 SELECT * FROM tab_1; call generateRandomData('tab_3','value',10000,100000); INSERT INTO tab_4 SELECT * FROM tab_3;
3)執行查詢語句,記錄執行時間
查詢語句及對應執行時間如下:
SELECT DISTINCT(`value`) FROM tab_1; SELECT `value` FROM tab_1 GROUP BY `value`; SELECT DISTINCT(`value`) FROM tab_2; SELECT `value` FROM tab_2 GROUP BY `value`; SELECT DISTINCT(`value`) FROM tab_3; SELECT `value` FROM tab_3 GROUP BY `value`; SELECT DISTINCT(`value`) FROM tab_4; SELECT `value` FROM tab_4 GROUP BY `value`;
4)實驗結果
表名 | 記錄數 | 查詢字段有無索引 | 查詢字段不同值個數 | DISTINCT | GROUP BY |
---|---|---|---|---|---|
tab_1 | 100000 | N | 3 | 0.058s | 0.059s |
tab_2 | 100000 | Y | 3 | 0.030s | 0.027s |
tab_3 | 100000 | N | 10000 | 0.072s | 0.073s |
tab_4 | 100000 | Y | 10000 | 0.047s | 0.049s |
實驗結論
MySQL 5.7.17中使用distinct和group by進行去重時,性能相差不大
實驗過程及結論,如有不足之處,歡迎指正,此實驗結論僅供參考。
總結
到此這篇關於MySQL去重中distinct和group by區別淺析的文章就介紹到這瞭,更多相關MySQL去重distinct和group by區別內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!