SQL查询如何按account_number去重,保留每个账号首次出现的行
问题原因排查
你当前编写的SQL逻辑存在缺陷:CTE仅获取了去重的account_number列表,和原表关联后仍会匹配到同一账号对应的所有重复记录,不会做过滤,因此无法得到仅保留首次出现行的效果。
正确查询方案
方案1:窗口函数法(推荐,兼容MySQL 8.0+、PostgreSQL、SQL Server等所有支持窗口函数的主流数据库)
SELECT id, account_number, account_name, account_chapter FROM ( SELECT *, ROW_NUMBER() OVER (PARTITION BY account_number ORDER BY id ASC) AS rn FROM accounts ) t WHERE rn = 1;
逻辑说明:
- 用
PARTITION BY account_number对所有记录按账号分组 - 组内按自增id升序排序,id最小的就是该账号首次出现的记录,对应行号
rn=1 - 最后筛选所有行号为1的记录即可得到预期结果
方案2:最小ID匹配法(兼容不支持窗口函数的低版本数据库,如MySQL 5.x)
SELECT a.* FROM accounts a INNER JOIN ( SELECT MIN(id) AS min_id, account_number FROM accounts GROUP BY account_number ) b ON a.id = b.min_id;
逻辑说明:
- 先通过分组聚合拿到每个账号对应的最小id(也就是首次出现的记录id)
- 再和原表关联拿到最小id对应的完整行数据即可
内容的提问来源于stack exchange,提问作者the smart life
相关产品推荐
相关产品推荐

