SQL Server关联表去重:按(Item,Recall_Date)筛选唯一行
解决SQL Server中按优先级保留(Item, Recall_Date)唯一行的方案
针对你遇到的重复记录问题,这里提供两种实用的SQL方案,完全匹配你指定的筛选优先级:
方法一:使用ROW_NUMBER()窗口函数(推荐)
这是处理这类分组去重+优先级筛选最常用的方式,逻辑清晰且性能稳定:
WITH RankedRecords AS ( SELECT *, -- 定义优先级排序规则:最高优先级是PingPong_FE=1且PingPong_Replen=1,其次是PingPong_FE=0 ROW_NUMBER() OVER ( PARTITION BY Item, Recall_Date -- 按需要去重的组合分组 ORDER BY CASE WHEN PingPong_FE = 1 AND PingPong_Replen = 1 THEN 1 WHEN PingPong_FE = 0 THEN 2 ELSE 3 -- 其他不符合条件的记录排最后,若不需要可后续过滤 END ASC, YourPrimaryKeyColumn DESC -- 可选:如果同优先级有多个行,按主键稳定选择(比如最新的) ) AS RowRank FROM YourTableName -- 替换成你的实际表名 ) SELECT -- 这里列出你需要保留的所有字段,避免选到RowRank Item, Recall_Date, PingPong_FE, PingPong_Replen, OtherColumn1, OtherColumn2 FROM RankedRecords WHERE RowRank = 1;
逻辑说明:
PARTITION BY Item, Recall_Date:把数据按你需要去重的组合分成独立的组ORDER BY CASE...:给每个组内的记录分配优先级,数字越小优先级越高ROW_NUMBER():给每个组内的记录按优先级排序编号,编号为1的就是我们要保留的唯一行- 如果你担心同优先级有多个记录(比如多个1/1的行),可以在ORDER BY里加主键或其他字段(比如创建时间)来确保选到固定的一行
方法二:使用子查询+EXISTS(适合简单场景)
如果你的数据量不大,也可以用EXISTS来逐行判断是否存在更高优先级的记录:
SELECT Item, Recall_Date, PingPong_FE, PingPong_Replen, OtherColumn1, OtherColumn2 FROM YourTableName t1 WHERE -- 优先保留1/1的记录:如果当前是1/1,或者同组里没有1/1的记录 (PingPong_FE = 1 AND PingPong_Replen = 1) OR ( PingPong_FE = 0 AND NOT EXISTS ( SELECT 1 FROM YourTableName t2 WHERE t2.Item = t1.Item AND t2.Recall_Date = t1.Recall_Date AND (t2.PingPong_FE = 1 AND t2.PingPong_Replen = 1) ) ) -- 可选:如果需要处理其他情况,继续加OR条件 GROUP BY Item, Recall_Date, PingPong_FE, PingPong_Replen, OtherColumn1, OtherColumn2;
逻辑说明:
- 先筛选出所有1/1的记录
- 再筛选出0的记录,但前提是同组里没有1/1的记录
- 最后用GROUP BY确保每个组合唯一(如果同优先级还有重复的话)
注意事项:
- 记得把代码里的
YourTableName和字段替换成你实际的表名和字段 - 建议先在测试环境验证逻辑,确保符合你的预期
- 如果有其他优先级规则,可以直接修改CASE语句或EXISTS条件
内容的提问来源于stack exchange,提问作者BTurkeli
相关产品推荐
相关产品推荐

