SQL面试题:除SELECT DISTINCT外,如何获取表中唯一行?
几种SQL去重获取唯一行的替代方法(替代DISTINCT)
针对你面试遇到的这个SQL去重问题,除了SELECT DISTINCT * FROM TableName;,还有以下几种常用的实现方法:
1. 使用GROUP BY分组
通过将所有需要去重的列作为分组依据,每个分组仅返回一行,实现去重效果:
SELECT Name, id, orderNo FROM TableName GROUP BY Name, id, orderNo;
这种方式和DISTINCT的底层逻辑类似,但如果后续需要对分组数据做聚合计算(比如统计重复次数),GROUP BY会更灵活。
2. 使用窗口函数ROW_NUMBER()
通过给重复分组内的行编号,筛选出每组的第一行来实现去重:
WITH RankedRows AS ( SELECT Name, id, orderNo, -- 按需要去重的列分组,给每组内的行编号 ROW_NUMBER() OVER (PARTITION BY Name, id, orderNo ORDER BY (SELECT NULL)) AS rn FROM TableName ) SELECT Name, id, orderNo FROM RankedRows WHERE rn = 1;
这里ORDER BY (SELECT NULL)是为了在不需要特定排序逻辑时兼容多数数据库,你也可以根据实际需求替换为具体列(比如如果有时间列,按时间排序保留最新行)。
3. 使用EXISTS子查询结合行标识符
通过判断当前行是否是分组中的“首行”来保留唯一记录,需要用到数据库自带的行唯一标识符(不同数据库写法不同):
-- PostgreSQL示例,用ctid作为行标识符 SELECT t1.Name, t1.id, t1.orderNo FROM TableName t1 WHERE NOT EXISTS ( SELECT 1 FROM TableName t2 WHERE t2.Name = t1.Name AND t2.id = t1.id AND t2.orderNo = t1.orderNo AND t2.ctid < t1.ctid ); -- MySQL示例,如果表有主键primary_id(注意这里指表的主键,不是数据里的id列) SELECT t1.Name, t1.id, t1.orderNo FROM TableName t1 WHERE NOT EXISTS ( SELECT 1 FROM TableName t2 WHERE t2.Name = t1.Name AND t2.id = t1.id AND t2.orderNo = t1.orderNo AND t2.primary_id < t1.primary_id );
这种方法适合需要精确控制保留哪一行的场景,比如保留最早插入的记录。
内容的提问来源于stack exchange,提问作者Aditya Patel
相关产品推荐
相关产品推荐

