首頁 > 軟體

MySQL去重中distinct和group by的區別淺析

2022-11-11 14:02:17

今天在寫業務需要對資料庫重複欄位進行去重時,因為是去重,首先想到的是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查詢快取。
  • 實驗表格:
表名記錄數查詢欄位有無索引查詢欄位不同值個數DISTINCTGROUP BY
tab_1100000N3  
tab_2100000Y3  
tab_3100000N10000  
tab_4100000Y10000  

實驗過程

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)實驗結果

表名記錄數查詢欄位有無索引查詢欄位不同值個數DISTINCTGROUP BY
tab_1100000N30.058s0.059s
tab_2100000Y30.030s0.027s
tab_3100000N100000.072s0.073s
tab_4100000Y100000.047s0.049s

實驗結論

MySQL 5.7.17中使用distinct和group by進行去重時,效能相差不大

實驗過程及結論,如有不足之處,歡迎指正,此實驗結論僅供參考。

總結

到此這篇關於MySQL去重中distinct和group by區別淺析的文章就介紹到這了,更多相關MySQL去重distinct和group by區別內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com