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

 更新时间:2022年11月09日 11:10:15   作者:小黑孩666  
今天无意中听到有同事在讨论,distinct和group by有什么区别,下面这篇文章主要给大家介绍了关于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查询缓存。
  • 实验表格:
表名记录数查询字段有无索引查询字段不同值个数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区别内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • SQL字符串以及数字常用操作汇总

    SQL字符串以及数字常用操作汇总

    本篇文章是对SQL字符串以及数字的常用操作进行了详细的总结与分析,需要的朋友参考下
    2013-06-06
  • MySQL千万级大表进行数据清理的几种常见方案

    MySQL千万级大表进行数据清理的几种常见方案

    当MySQL数据库中的表数据量达到千万级别时,直接对数据进行删除操作将面临严重的性能问题,可能会导致数据库长时间的锁表,因此,如何安全高效地进行数据清理成为一个亟需解决的问题,下面我将分享几种常见的数据清理方案,需要的朋友可以参考下
    2023-11-11
  • MySQL中对于NULL值的理解和使用教程

    MySQL中对于NULL值的理解和使用教程

    这篇文章主要介绍了MySQL中对于NULL值的理解和使用教程,是MySQL入门学习中的基础知识,需要的朋友可以参考下
    2015-11-11
  • MySQL 全文索引使用指南

    MySQL 全文索引使用指南

    在 MySQL 中,我们经常使用 WHERE 条件用于进行值的相等比较、范围过滤。然而,我们也会使用关键字进行搜索,这个基于搜索值与其他值的相关性来进行过滤。MySQL全文检索即用于这种场景。本篇将介绍如何使用全文检索。
    2021-05-05
  • MySql用DATE_FORMAT截取DateTime字段的日期值

    MySql用DATE_FORMAT截取DateTime字段的日期值

    MySql截取DateTime字段的日期值可以使用DATE_FORMAT来格式化,使用方法如下
    2014-08-08
  • mysql 5.7.23 winx64解压版安装教程

    mysql 5.7.23 winx64解压版安装教程

    这篇文章主要为大家详细介绍了mysql 5.7.23 winx64解压版安装教程,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-09-09
  • mysql  通配符(sql 高级过滤)

    mysql 通配符(sql 高级过滤)

    这篇文章主要介绍了mysql 通配符,通配符是对操作符的一种补充,操作符都确认的,而通配符属于模糊的
    2021-10-10
  • MySQL中删除重复数据的简单方法

    MySQL中删除重复数据的简单方法

    这篇文章主要介绍了MySQL中删除重复数据的简单方法,比起一般的NOT IN语句的效率更为高,需要的朋友可以参考下
    2015-05-05
  • InnoDB解决幻读的方法详解

    InnoDB解决幻读的方法详解

    这篇文章主要介绍了InnoDB解决幻读的方法详解的相关资料,需要的朋友可以参考下
    2023-04-04
  • mysql 字符串正则表达式及说明

    mysql 字符串正则表达式及说明

    这篇文章主要介绍了mysql 字符串正则表达式及说明,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-08-08

最新评论