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区别内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!