如何仅移除分组中成对出现的重复数据?
仅移除成对重复记录的通用SQL方案
原始数据
| id_1 | id_2 | colA | colB | colC |
|---|---|---|---|---|
| 1 | 2 | 2022-01-02 | scroll fast | 12 |
| 1 | 2 | 2022-01-02 | scroll fast | 12 |
| 1 | 3 | 2022-01-03 | scroll fast fast | 11 |
| 1 | 3 | 2022-01-03 | scroll fast fast | 11 |
| 1 | 3 | 2022-01-03 | scroll fast fast | 11 |
需求
只消除完全成对的重复项:
- 重复次数为偶数的记录组,保留一半(比如2条留1条)
- 重复次数为奇数的记录组,全部保留(比如3条全留)
不能仅靠id_1、id_2过滤,需要适配大规模数据集的通用方案。
解决方案
WITH ranked_records AS ( SELECT *, -- 给每组重复记录分配行号 ROW_NUMBER() OVER (PARTITION BY id_1, id_2, colA, colB, colC ORDER BY (SELECT NULL)) AS rn, -- 统计每组重复记录的总条数 COUNT(*) OVER (PARTITION BY id_1, id_2, colA, colB, colC) AS total_count FROM your_table ) SELECT id_1, id_2, colA, colB, colC FROM ranked_records WHERE -- 奇数条重复,全保留 total_count % 2 = 1 -- 偶数条重复,只保留一半 OR rn <= total_count / 2;
逻辑说明
- 分组标记:用
PARTITION BY把所有完全相同的记录归为一组,同时给每组内的记录编行号,统计每组总条数。 - 筛选规则:
- 要是组里记录数是奇数,直接全留
- 要是偶数,只留前一半,刚好把成对的重复去掉一半
注:ORDER BY (SELECT NULL)是为了兼容大部分数据库的窗口函数语法(部分数据库要求窗口函数必须带ORDER BY),如果你的数据库允许窗口函数省略ORDER BY,可以直接去掉这部分。
内容的提问来源于stack exchange,提问作者Vendetta
相关产品推荐
相关产品推荐

