MySQL中数据去重的两种方式详解(DISTINCT和GROUP BY)

 更新时间:2025年09月28日 08:40:04   作者:程序新视界  
在日常工作中,数据库查询操作无处不在,而处理数据中的重复项与分组汇总是非常常见的需求,MySQL提供了两种常见的方式来管理和检索唯一值:SELECT DISTINCT和GROUP BY,这篇文章带大家将从功能、性能以及实际应用等方面详细介绍DISTINCT和GROUP BY的差异

引言

在日常工作中,数据库查询操作无处不在,而处理数据中的重复项与分组汇总是非常常见的需求。MySQL 提供了两种常见的方式来管理和检索唯一值:SELECT DISTINCTGROUP BY。这两者虽然在生成输出上可能相似,但用途与性能各有不同,使用场景也有所区分。

这篇文章带大家将从功能、性能以及实际应用等方面详细介绍 DISTINCTGROUP BY 的差异,并结合具体的示例数据来理解其使用场景。

SELECT DISTINCT

DISTINCT 是一个用于去重的关键字。SELECT DISTINCT 语句用于从结果集中删除重复行,只返回唯一值。因此,在需要仅获取数据的唯一部分时,DISTINCT 是一种简单高效的方式。

基本语法

SELECT DISTINCT column1, column2
FROM table_name;

参数说明:

  • column1, column2:要检索的字段名。
  • table_name:查询的表名。

特性说明

  • DISTINCT 可以基于单列或多列进行去重,只有多列的值完全相同时,才会被判定为重复行。
  • DISTINCT中,NULL 被视为一个独立的值,因此即使列中有多个 NULL 值,结果中只会保留一个 NULL

GROUP BY

GROUP BY 是一个用于分组的子句,通常与聚合函数配合使用以对分组后的数据进行汇总处理。它按指定列的值将行划分为不同的组。

基本语法

SELECT column1, aggregate_function(column_name)
FROM table_name
WHERE condition
GROUP BY column1, column2, ...;

参数说明:

  • column1, column2:分组的字段。
  • aggregate_function(column_name) :用于对分组内的行进行计算的聚合函数,例如 COUNT, SUM, AVG 等。
  • table_name:查询的表名字。
  • condition:可选,用于过滤行,在分组之前应用。
  • GROUP BY column1, column2... :定义用于分组的字段,具有相同值的行被分配到同一个组。

示例表结构与数据:

为了便于说明,我们定义两个表 customersorders,并插入一些示例数据。

创建表:

CREATE TABLE customers (
  customer_id INT PRIMARY KEY,
  name VARCHAR(255) NOT NULL,
  city VARCHAR(255) NOT NULL
);
​
INSERT INTO customers (customer_id, name, city) VALUES
  (1, 'John Doe', 'New York'),
  (2, 'Jane Smith', 'London'),
  (3, 'Mike Brown', 'Paris'),
  (2, 'Jane Smith', 'London'); -- 存在重复项
​
CREATE TABLE orders (
  order_id INT PRIMARY KEY,
  customer_id INT NOT NULL,
  product VARCHAR(255) NOT NULL,
  price DECIMAL(10,2) NOT NULL,
  FOREIGN KEY (customer_id) REFERENCES customers(customer_id)
);
​
INSERT INTO orders (order_id, customer_id, product, price) VALUES
  (1, 1, 'Phone', 100.00),
  (2, 2, 'Laptop', 500.00),
  (3, 1, 'Tablet', 200.00),
  (4, 2, 'Watch', 150.00);

SELECT DISTINCT与GROUP BY使用对比

示例 1:检索唯一的客户城市

场景:我们希望查询 customers 表中的唯一城市,不关心重复的城市名称。

使用 DISTINCT

SELECT DISTINCT city
FROM customers;

输出:

city
-----
New York
London
Paris

解释:

  • SQL 查询去除了数据集中重复的城市,只返回唯一值,简单直观。

示例 2:按客户城市统计订单数量

场景:我们希望统计每个城市对应的订单数量,涉及分组统计。

使用 GROUP BY

SELECT city, COUNT(*) AS order_count
FROM customers c
INNER JOIN orders o ON c.customer_id = o.customer_id
GROUP BY city;

输出:

city         order_count
------------------------
London       2
New York     2

解释:

  • SQL 查询通过 GROUP BY 以城市分组,并结合 COUNT 聚合函数统计每组的订单数量,提供了更丰富的汇总信息。

SELECT DISTINCT 与 GROUP BY 的性能分析

虽然 DISTINCTGROUP BY 都会涉及底层的分组操作,但在某些情况下,它们可以互换使用,而在性能、功能上的表现会有所偏差。

两者实现的相似性

对于以下两条查询:

SELECT DISTINCT int1_index FROM test_table;
SELECT int1_index FROM test_table GROUP BY int1_index;

在某些情况下(如 int1_index 上有索引),两者使用相同的执行计划。例如,通过以下 EXPLAIN 分析,查询会通过索引扫描优化:

mysql> explain select distinct int1_index from test_distinct_groupby;
mysql> explain select int1_index from test_distinct_groupby group by int1_index;

两者结果中 Extra 字段显示 Using index for group-by,说明索引用于优化查询,效率相当。

GROUP BY的隐式排序问题

在 MySQL 8.0 之前,GROUP BY 默认对结果进行隐式排序。这可能导致额外的排序操作(filesort),增加了查询开销。在无显式排序要求时,DISTINCT 的性能会优于 GROUP BY

例如:

SELECT int6_random FROM test_table GROUP BY int6_random;

通过 EXPLAIN 查询,可以看到隐式排序增加了开销:

Extra: Using filesort

从 MySQL 8.0 开始,GROUP BY 不再强制进行隐式排序,性能接近 DISTINCT,尤其是在无索引的大数据场景下,二者效率更加一致。

SELECT DISTINCT 与 GROUP BY 的应用场景及差异

功能和目的对比:

功能SELECT DISTINCTGROUP BY
目的去重分组并聚合数据
是否支持聚合函数
排序行为否(可选)是(默认排序,8.0后优化)
性能无索引场景更高效无索引场景稍慢(排序)
语法复杂度简单较复杂

适用场景

根据具体需求选择 DISTINCTGROUP BY

  1. 使用SELECT DISTINCT
  • 当仅需要去除重复项,返回唯一值时。
  • 适用于简单查询场景。
  1. 使用GROUP BY
  • 当需要按特定条件分组并对分组内的数据进行汇总或聚合(如 COUNT, SUM, AVG)时。
  • 适合复杂的业务场景,支持更多灵活的操作,如结合 HAVING 子句筛选分组后的结果。

结论

SELECT DISTINCTGROUP BY 是两种功能强大的工具,用于不同类型的 SQL 查询需求:

  • DISTINCT 适合简单去重,避免数据重复。
  • GROUP BY 更注重分组数据并对分组进行汇总分析。

在 MySQL 8.0 后,性能差距进一步缩小,但从语义清晰度与灵活性来看,GROUP BY 在处理复杂业务场景时更胜一筹。选择使用哪种方式应根据具体应用场景而定。

以上就是MySQL中数据去重的两种方式详解(DISTINCT和GROUP BY)的详细内容,更多关于MySQL数据去重方式的资料请关注脚本之家其它相关文章!

相关文章

  • Mysql中使用sql语句生成雪花算法Id

    Mysql中使用sql语句生成雪花算法Id

    雪花算法是一种生成全局唯一ID的分布式算法,本文主要介绍了Mysql中使用sql语句生成雪花算法Id,具有一定的参考价值,感兴趣的可以了解一下
    2025-02-02
  • Linux中如何查看mysql版本问题

    Linux中如何查看mysql版本问题

    这篇文章主要介绍了Linux中如何查看mysql版本问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教
    2023-09-09
  • Mysql中的存储过程超详细讲解

    Mysql中的存储过程超详细讲解

    这篇文章主要介绍了Mysql中的存储过程超详细讲解,包括存储过程基本语法,感兴趣的朋友一起看看吧
    2025-04-04
  • MySQL查询JSON数组字段包含特定字符串的方法

    MySQL查询JSON数组字段包含特定字符串的方法

    在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种高效的解决方案吧
    2025-06-06
  • 腾讯面试:一条SQL语句执行得很慢的原因有哪些?---不看后悔系列(推荐)

    腾讯面试:一条SQL语句执行得很慢的原因有哪些?---不看后悔系列(推荐)

    这篇文章主要介绍了SQL语句执行慢的原因,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-04-04
  • MySQL存储IP地址的方法

    MySQL存储IP地址的方法

    本文介绍了MySQL存储IP地址的方法其目的就是最大限度的优化性能,需要的朋友可以参考下
    2015-07-07
  • 用SQL实现统计报表中的"小计"与"合计"的方法详解

    用SQL实现统计报表中的"小计"与"合计"的方法详解

    本篇文章是对使用SQL实现统计报表中的"小计"与"合计"的方法进行了详细的分析介绍,需要的朋友参考下
    2013-06-06
  • MySQL到Kafka实时数据同步

    MySQL到Kafka实时数据同步

    很多 DBA 同学经常会遇到要从一个数据库实时同步到另一个数据库的问题,同构数据还相对容易,遇上异构数据、表多、数据量大等情况就难以同步,我自己亲测了一种方式,可以非常方便的实现MySQL Kafka实时数据同步,需要的朋友可以参考下
    2024-01-01
  • MySQL教程数据定义语言DDL示例详解

    MySQL教程数据定义语言DDL示例详解

    这篇文章主要为大家介绍了MySQL教程中什么是数据定义语言DDL的示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-10-10
  • 一文深入探究MySQL自增锁

    一文深入探究MySQL自增锁

    MySQL的自增锁是指在使用自增主键(Auto Increment)时,为了保证唯一性和正确性,系统会对自增字段进行加锁,这样可以确保同时插入多条记录时,每条记录都能够获得唯一的自增值,本将和大家一起深入探究MySQL自增锁,需要的朋友可以参考下
    2023-08-08

最新评论