distinct 和 group by有什么区别

本文详细对比了MySQL中distinct和group by两种去重方式,包括单列、多列去重,以及配合聚合函数的应用。讨论了两者在查询结果、业务场景和性能上的差异,并总结了适用场景和性能优劣。

在mysql中,最常见的去重方式有两种:使用distinct或使用group by ,那它们有什么区别

1、创建测试数据

-- 创建测试表
drop table if exists pageview;
create table pageview(
    id bigint primary key auto_increment comment '自增主键',
    aid bigint not null comment '文章ID',
    uid bigint not null comment '(访问)用户ID',
    createtime datetime default now() comment '创建时间'
) default charset='utf8mb4';
-- 添加测试数据
insert into pageview(aid,uid) values(1,1);
insert into pageview(aid,uid) values(1,1);
insert into pageview(aid,uid) values(2,1);
insert into pageview(aid,uid) values(2,2);

显示的效果如下:
在这里插入图片描述

2、distinct使用

distinct基本语法如下:

SELECT DISTINCT column_name,column_name FROM table_name;
2.1 单列去重

我们先用 distinct 实现单列去重,根据 aid(文章 ID)去重,具体实现如下:

select distinct aid from pageview

在这里插入图片描述

2.2 多列去重

除了单列去重之外,distinct还支持多列(两列及以上)去重,我们根据aid(文章id)和uid(用户id)联合去重,具体实现如下:

select distinct aid,uid from pageview

在这里插入图片描述

2.3 聚合函数+去重

使用distinct + 聚合函数去重,计算aid去重之后的总条数,具体实现如下:

select count(distinct aid) from pageview

在这里插入图片描述

3 group by使用

group by 基本语法如下:

SELECT column_name,column_name FROM table_name 
WHERE column_name operator value 
GROUP BY column_name
3.1 单列去重

根据aid去重,具体实现如下:

select * from pageview group by aid;

在这里插入图片描述
与distinct相比group by 可以显示更多的列,而distinct只能展示去重的列。

3.2 多列去重

根据 aid(文章 ID)和 uid(用户 ID)联合去重,具体实现如下:

select * from pageview group by aid,uid;

在这里插入图片描述

3.3 聚合函数 + group by

统计每个 aid 的总数量,SQL 实现如下:

select aid,count(aid) from pageview group by aid

在这里插入图片描述
从上述结果可以看出,使用 group by 和 distinct 加 count 的查询语义是完全不同的,distinct + count 统计的是去重之后的总数量,而 group by + count 统计的是分组之后的每组数据的总数

4 distinct和group by 区别

1、区别1:查询结果集不同
当使用distinct去重时,查询结果集中只有去重列信息
如下所示:

select  distinct aid from pageview;

在这里插入图片描述
当你试图添加非去重字段(查询)时,SQL 会报错如下图所示:
在这里插入图片描述
而使用 group by 排序可以查询一个或多个字段,如下图所示:

select * from pageview group by aid;

在这里插入图片描述

2、区别2:使用业务场景不同
统计去重之后的总数量需要使用 distinct,而统计分组明细,或在分组明细的基础上添加查询条件时,就得使用 group by 了。使用 distinct 统计某列去重之后的总数量:

select aid,count(distinct aid) from pageview;

在这里插入图片描述
统计分组之后数量大于2的文章,就要使用group by,如下图所示:

-- 统计分组之后数量大于 2 的文章
select * from pageview group by aid having count(aid) >= 2

在这里插入图片描述

3、区别3:性能不同
如果去重的字段有索引,那么group by 和distinct都可以使用索引,此情况他们的性能是相同的;而当去重的字段没有索引时,distinct的性能就会高于group by ,因为在MySQL8.0之前,group by 有一个隐藏的功能会进行默认的排序,这样就会触发filesort从而导致查询性能降低。

总结:
大部分场景下distinct是特殊的group by ,但是二者也有细微的区别,比如他们在查询结果集上,使用的具体业务场景上,以及性能上都是不同的。

<think>好的,用户现在问的是DISTINCTGROUP BY区别。之前他已经问过关于SELECT COUNT(DISTINCT faaexplain)的查询,我详细解释了DISTINCT的作用。现在他可能想进一步了解这两个关键字的不同使用场景功能。 首先,我需要回忆这两个关键字的用途。DISTINCT用于去重,返回唯一值;而GROUP BY则是分组,通常与聚合函数一起使用。用户可能在使用中遇到了混淆,比如什么时候用DISTINCT,什么时候用GROUP BY,或者是否两者可以互换。 接下来,我需要考虑用户的实际使用场景。用户之前接触的是登录记录表,涉及统计不同登录原因的数量。现在的问题可能来源于他在处理类似数据时,遇到了需要分组统计的情况,或者看到别人写的SQL中用了GROUP BY而想了解区别。 用户的身份可能是数据分析师或开发人员,需要编写SQL查询来处理数据。他们的真实需求可能是优化查询,或者正确选择关键字以准确获取所需结果。深层需求可能包括理解两者的性能差异,避免在错误场景下使用导致结果不正确或效率低下。 然后,我需要组织两者的区别,从功能、使用场景、输出结果、性能等方面进行比较。同时要给出示例,帮助用户更直观地理解。比如,DISTINCT单纯去重,而GROUP BY分组后可以计算每组的汇总值。 还要注意提到两者的组合使用情况,比如在GROUP BY之后使用DISTINCT,虽然不常见,但可能有其用途。同时,性能方面,DISTINCTGROUP BY在某些数据库中的执行方式可能不同,影响查询速度。 最后,总结两者的适用场景,帮助用户根据需求选择合适的关键字。确保解释清晰,结构分明,用例子辅助理解,避免技术术语过多,让用户容易掌握核心区别。</think>以下是关于 `DISTINCT` `GROUP BY` 的核心区别及使用场景的详细解释: --- ### **1. 核心功能对比** | **特性** | **`DISTINCT`** | **`GROUP BY`** | |-------------------|--------------------------------|---------------------------------| | **主要目的** | 消除重复行,返回唯一值 | 按指定列分组,并对每组进行聚合计算 | | **输出结果** | 直接返回去重后的所有列值 | 返回分组列 + 每组的聚合结果(如COUNT、SUM) | | **是否支持聚合** | 仅去重,不计算聚合值 | 必须配合聚合函数(如SUM、AVG)使用 | | **灵活性** | 只能控制最终输出的唯一性 | 可同时分组、过滤(HAVING)、排序等 | --- ### **2. 典型使用场景** #### **(1)`DISTINCT` 适用场景** - **简单去重**:仅需列出某列(或组合列)的所有唯一值。 ```sql -- 查询所有不同的用户登录设备类型 SELECT DISTINCT device_type FROM mz_loginrecord; ``` - **统计唯一值数量**:配合`COUNT`统计唯一值总数。 ```sql -- 统计最近7天出现过的不同登录错误类型数量 SELECT COUNT(DISTINCT faaexplain) FROM mz_loginrecord WHERE createtime >= CURDATE() - INTERVAL 7 DAY; ``` #### **(2)`GROUP BY` 适用场景** - **分组聚合**:按某列分组后,计算每组的统计值。 ```sql -- 统计每种登录设备的日均登录次数 SELECT device_type, COUNT(*) AS daily_logins, AVG(login_time) AS avg_time FROM mz_loginrecord GROUP BY device_type; ``` - **分组过滤**:使用`HAVING`对分组结果筛选。 ```sql -- 筛选出单日登录次数超过100次的设备类型 SELECT device_type, COUNT(*) AS logins FROM mz_loginrecord GROUP BY device_type HAVING logins > 100; ``` --- ### **3. 关键区别详解** #### **(1)输出内容不同** - **`DISTINCT`** 返回所有列的**唯一组合**。例如: ```sql SELECT DISTINCT name, age FROM users; -- 输出唯一的(name, age)组合 ``` - **`GROUP BY`** 返回分组列 + 聚合结果。例如: ```sql SELECT name, COUNT(*) FROM users GROUP BY name; -- 每个name对应的记录数 ``` #### **(2)聚合能力不同** - **`DISTINCT`** 无法计算每组的统计值(如总、平均值)。 - **`GROUP BY`** 必须配合聚合函数(如`SUM`、`AVG`、`MAX`)使用,直接输出分组统计结果。 #### **(3)执行顺序差异** - **`DISTINCT`** 在`SELECT`阶段最后一步执行去重。 - **`GROUP BY`** 先分组聚合,再输出结果(可通过`HAVING`进一步过滤分组结果)。 --- ### **4. 性能对比** - **数据量较小时**:`DISTINCT` `GROUP BY` 效率差异不大。 - **数据量大时**: - `DISTINCT` 需要对所有列组合进行去重,可能更耗资源。 - `GROUP BY` 若仅需分组统计(无需所有列),可能效率更高。 - **优化建议**: - 若只需统计唯一值数量,优先用`COUNT(DISTINCT column)`。 - 若需分组后多维度分析,必须用`GROUP BY`。 --- ### **5. 特殊场景:`DISTINCT` 与 `GROUP BY` 组合** 虽然不常见,但可以结合使用(通常用于复杂查询): ```sql -- 先按department分组,再对分组后的job_title去重统计 SELECT department, COUNT(DISTINCT job_title) FROM employees GROUP BY department; ``` --- ### **6. 总结** | **选择依据** | **使用 `DISTINCT`** | **使用 `GROUP BY`** | |---------------------------|-----------------------------|-----------------------------| | **是否需要聚合统计** | 否 | 是 | | **是否需要输出所有列** | 是(需唯一组合) | 否(仅分组列+聚合结果) | | **是否需要过滤分组结果** | 否 | 是(需配合`HAVING`) | **简记**: - 单纯去重 → `DISTINCT` - 分组统计 → `GROUP BY`
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值