distinct:
distinct作为mysql的关键字,其主要作用是用来表中的单个字段或多个字段去重操作,过滤重复的记录。
语法结构:
SELECT DISTINCT
【字段名】
FROM
【表名】
WHERE
【wher条件】;
例如:select distinct age from student where age > 12;
DISTINCT 关键词用于返回唯一不同的值。 如果要过滤掉name和id两个字段都重复的记录的话则需要distinct name,id这样写,但如果如果sql这样写:select id,distinct name from user,mysql就会报错,所以DISTINCT关键词要放在查询语句中的第一个字段前使用,且作用于主句所有列。
如果列具有NULL值,并且对该列使用DISTINCT子句,MySQL将保留一个NULL值,并删除其它的NULL值,因为DISTINCT子句将所有NULL值视为相同的值。
distinct 多列:将distinct子句与多列一起使用时,MySQL使用这些列中的值组合来确定结果集中的唯一性。
distinct语句与group by 语句在不使用聚合函数的情况下在select语句中使用group by子句,则group by子句的行为与distinct子句类似。
group by:
group by的使用和distinct类似,都有基础的去重操作。
语法结构:
SELECT DISTINCT
【字段名】
FROM
【表名】
WHERE
【wher条件】
GROUP BY
【上面的字段名之一】;
group by的常规用法是配合聚合函数,利用分组信息进行统计,常见的是配合max等聚合函数筛选数据后分析,以及配合having进行筛选后过滤。
group by语句执行流程:
执行以下语句:SELECT b, count(*) as num from t1 GROUP BY b HAVING b<100;
如果b没有索引的话,此语句就会进行全表扫描。 字段b上没有索引,则它的执行顺序是这样的:
- 创建内存临时表,表里有两个字段 b 和 c,主键是 b;
- 对t1表进行全表扫描,并取出第一条数据,判断b是否小于100。如果b<100,就记录b的值为X,并存入临时表。
1.如果临时表中没有主键为b的行,就插入一条记录 b,c(x,1)
2.如果临时表中有主键为b的行,就更新主键为b的这一行,并把c的值进行加1 - 遍历完成后,再根据字段 b做排序,得到结果集返回给客户端。
distinct和group by比较:
在大多数例子中,DISTINCT可以被看作是特殊的GROUP BY,它们的实现都基于分组操作,且都可以通过松散索引扫描、紧凑索引扫描来实现。
1)查询结果集不同:
当使用 distinct 去重时,查询结果集中只有去重列信息,而使用 group by 排序可以查询一个或多个字段
2)使用业务场景不同:
统计去重之后的总数量需要使用 distinct,而统计分组明细,或在分组明细的基础上添加查询条件时,就得使用 group by 了
3)性能不同:
在有索引的情况下:group by和distinct都能使用索引,效率相同。
在无索引的情况下:distinct效率高于group by。原因是distinct 和 group by都会进行分组操作,但`group by`可能会进行排序,触发filesort,导致sql执行效率低下。