PostgreSQL中如何基于单列删除表内重复行?
在PostgreSQL中按ci_nodename删除重复行
没问题,针对你要基于ci_nodename列删除重复行、保留最小ruleid对应行的需求,这里有两种实用的解决方案,完全适配你的数据场景:
方法一:使用DELETE USING子句(高效直接)
这种方法通过自关联表定位重复行,删除每个ci_nodename组中ruleid较大的重复项,刚好匹配你期望保留最小ruleid的需求。假设你的表名为rules(记得替换成实际表名):
DELETE FROM rules r1 USING rules r2 WHERE r1.ci_nodename = r2.ci_nodename AND r1.ruleid > r2.ruleid;
逻辑说明
- 我们将表自身关联为
r1和r2,匹配相同ci_nodename的行 - 只删除
r1中ruleid比r2大的行,这样每个ci_nodename最终只会留下ruleid最小的那一行
方法二:使用窗口函数(直观灵活)
如果后续需要调整去重规则(比如改成保留最大ruleid),窗口函数的方式会更易修改:
WITH ranked_rules AS ( SELECT ruleid, -- 按ci_nodename分组,每组内按ruleid升序排,最小的行得到rn=1 ROW_NUMBER() OVER (PARTITION BY ci_nodename ORDER BY ruleid) AS rn FROM rules ) DELETE FROM rules WHERE ruleid IN (SELECT ruleid FROM ranked_rules WHERE rn > 1);
逻辑说明
- 先用CTE给每行分配一个行号
rn:同一ci_nodename的行按ruleid从小到大排序,第一行(最小ruleid)的rn为1 - 然后删除所有
rn > 1的行,也就是每个组里的重复项
扩展提示
如果后续需要保留最大的ruleid,只需要把ORDER BY ruleid改成ORDER BY ruleid DESC即可。
重要提醒
操作删除前,建议先执行查询确认要删除的行,避免误删:
- 对应方法一,执行:
SELECT r1.* FROM rules r1 USING rules r2 WHERE r1.ci_nodename = r2.ci_nodename AND r1.ruleid > r2.ruleid; - 对应方法二,执行:
SELECT * FROM rules WHERE ruleid IN ( SELECT ruleid FROM ( SELECT ruleid, ROW_NUMBER() OVER (PARTITION BY ci_nodename ORDER BY ruleid) AS rn FROM rules ) ranked_rules WHERE rn > 1 );
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

