跳转到主内容
极星编程网:以代码为星,赴技术山海!

如何查询SQL表中某列的唯一值列表_使用DISTINCT或GROUP BY

DISTINCT 是标准、简洁、高效的选择;GROUP BY 在只查唯一值时属于“杀鸡用牛刀”,除非同时需聚合计算。 查唯一值该用
DISTINCT
还是
GROUP BY
直接说结论:
DISTINCT
是标准、简洁、高效的选择;
GROUP BY
在只查唯一值时属于“杀鸡用牛刀”,除非你同时要聚合计算(比如统计每个值出现几次)。很多人误以为两者等价,其实语义和执行逻辑完全不同。 常见错误现象:用
GROUP BY
只写一个字段却没加聚合函数,结果看似能跑通,但一旦换数据库(比如从 MySQL 切到 PostgreSQL 或 SQL Server)就直接报错——因为严格 SQL 标准要求
SELECT
中所有非聚合字段必须出现在
GROUP BY
子句里。
DISTINCT
是集合操作,语义清晰:“我要这一列所有不重复的值”
GROUP BY
是分组操作,语义是“按这些字段把行归成若干组,每组算一个结果”,单列无聚合时只是副作用 性能上,多数引擎对
DISTINCT
有专门优化(如哈希去重),而
GROUP BY
通常触发更重的分组流程 什么时候非得用
GROUP BY
而不是
DISTINCT
当你不只是要唯一值,还要知道每个值的附加信息时。
GROUP BY
才是正确工具,
DISTINCT
做不到。 典型场景:查用户表中每个
country
的唯一值,同时统计人数、取最早注册时间、列出前 3 个用户名……这些都必须靠
GROUP BY
+ 聚合函数。 统计频次:
SELECT country, COUNT(*) FROM users GROUP BY country
带条件聚合:
SELECT status, AVG(amount) FROM orders GROUP BY status HAVING AVG(amount) > 100
多字段去重并取最新记录(需配合窗口函数或子查询):
GROUP BY user_id
配合
MAX(created_at)
是常见起点 注意:
HAVING
必须跟在
GROUP BY
后,不能用于
DISTINCT
查询——这是语法硬限制。
DISTINCT
的常见坑与绕过方法
DISTINCT
看似简单,但实际用错频率很高。核心问题是它作用于整行,不是单列——哪怕你只写了一个字段,底层仍是先取所有匹配行、再对整行做去重。 想查
name
唯一值,但表里有
id
,
name
,
email
三列,写
SELECT DISTINCT name FROM t
没问题;但若写
SELECT DISTINCT name, email FROM t
,得到的是“name+email”组合唯一,不是
name
单独唯一
NULL
被视为相同值:所有
NULL
会被合并成一条,这是标准行为,但容易被忽略 性能隐患:如果列上有大量重复值,
DISTINCT
仍需扫描全表;加索引对去重本身帮助有限,但可加速
WHERE
过滤阶段 想排除
NULL
再去重?加
WHERE column IS NOT NULL
,别指望
DISTINCT
自动过滤 MySQL 和 PostgreSQL 对
GROUP BY
的宽容度差异 MySQL 5.7 默认开启
ONLY_FULL_GROUP_BY
之前,允许
SELECT a, b FROM t GROUP BY a
(
b
不在
GROUP BY
里也不聚合),结果是返回每组第一条的
b
值——这既不标准也不可预测。PostgreSQL、SQL Server、Oracle 一律拒绝这种写法。 这意味着:依赖 MySQL “宽松模式” 写的
GROUP BY
查询,迁移到其他数据库大概率失败。 安全写法永远是:所有非聚合字段必须显式出现在
GROUP BY
如果真只需要唯一值,别碰
GROUP BY
——省事、可移植、不易出错 检查当前 MySQL 模式:
SELECT @@sql_mode
,确认是否含
ONLY_FULL_GROUP_BY
最易被忽略的一点:即使你只想要唯一值,如果后续要加排序或分页,
DISTINCT
和
GROUP BY
的执行顺序、索引利用方式也不同,可能导致分页结果不稳定——尤其在高并发更新场景下。

相关文章