运营要「下过单的用户数」,新人写了 select count(user_id) from orders,数字比实际多三成,因为一个用户下了好几单。改成 count(distinct user_id) 才对得上。
distinct 作用在整行上,不是某一列,这一点先记住,后面绝大多数误用都出在这。
多列 distinct 去的是组合
select distinct city, level from users 去掉的是(city, level)这个组合,不是 city。想每个城市只出一行,用 group by 更直白,后来接手的人也不会读错。
count 里塞多列在 MySQL 直接报错,得套一层子查询:select count(*) from (select distinct city, level from users) t;
NULL 会被算成一类
distinct 把多个 NULL 归并成一个,count(distinct col) 却不数 NULL。要统计空值数量,用 count(*) 减 count(col)。做报表时这个差值是「未填写」那一行,少了就对不上总数。
distinct 和 group by 怎么选
只想去重看数据,distinct 写得短;去重之后还要算个数、求和、按条件筛,只能 group by 配聚合函数和 having。单表上两者结果等价,execution plan 也常被优化器改写成一模一样,explain 看一下就知道。
性能上别乱用
distinct 本质要排序或哈希,大表上比 group by 略慢;已经有唯一索引的列再加 distinct,纯属白花钱。
更常见的是 join 把行放大了再去重,等于先制造重复再消除。先看 join 条件是不是漏了,比加 distinct 有用得多。
口径也要先问清楚:要下单用户数还是订单数,算新客还是全部。口径错了,语法再对,报表也是错的。