报表里城市一列重复了十几行,第一反应就是加个 distinct。它写在 select 后面,作用是把结果里重复的行去掉,只留一份。

单列去重和多列去重

select distinct city from users;
select distinct city, district from users;

第一句好理解,城市去重。第二句要注意:distinct 不是只对 city 去重,而是对 city 加 district 的组合去重,同一个城市的不同区算不同组合,都会保留。很多人以为 distinct 写在第一列就只管第一列,结果数据还是重的,就是这里没搞清。

和 count 搭配的口径

distinct用法里最容易混的是和 count 的搭配。

select count(distinct city) from users;

这是统计去重后的城市数量。注意括号位置,把多个列都塞进同一个括号里,在 MySQL 会直接报错,想按组合计数,得先把两列拼起来再数,或者套一层子查询。

几个容易踩的点

  • distinct 作用于整个 select 列表,不是紧跟它的那一列
  • 带它的查询配合 order by 时,排序字段最好也在 select 列表里,否则部分版本会报错
  • null 也算一种取值,去重后 null 只保留一行
  • 去重需要排序或哈希,数据量大时先 where 过滤再 distinct,别全表去完再筛

相近的写法还有 group by,单列去重两者结果一样,但 group by 是配合聚合函数用的,语义不同。distinct用法就这几条规则,口径拿不准时先拿小表跑一遍对数,比猜快得多。