MySQL去重中distinct和group by的区别浅析

2022-11-11 09:24:28

今天在写业务需要对数据库重复字段进行去重时,因为是去重,首先想到的是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区别内容请搜索易采站长站以前的文章或继续浏览下面的相关文章希望大家以后多多支持易采站长站!