我们试图以删除重复项而不是抛出错误的方式为postgres表添加唯一约束。唯一约束跨越两列,并且没有主键。例如:
i_id | term | date_created
1 | 'mako' | 123456789
1 | 'mako' | 123451234
1 | 'tele' | 213456852
2 | 'rake' | 598521542
因此,在这个例子中,我们需要删除第二行才能安全地添加唯一约束。通常我们会执行一个带有select distinct的delete命令,但是我们没有任何行的区别键。具体来说,唯一键将位于列[i_id,term]。
之上(WTF从一开始就没有一个独特的约束?去图。)
我认为删除声明是最好的,但我不能简单地写
delete from table where row_id not in (select row_id ... distinct something ... )
因为该行没有主键。如果可能的话,我宁愿避开临时桌子。有什么建议吗?
编辑:抱歉。我们正在使用postgres 8.4。编辑2:我们使用的解决方案是:
delete from table where ctid not in (
select
distinct on (i_id, term)
ctid
from table
order by i_id, term
);
谢谢你们!
答案 0 :(得分:2)
DELETE FROM the_table
WHERE ctid NOT IN (SELECT min(b.ctid)
FROM the_table b
GROUP BY b.i_id, b.term)
答案 1 :(得分:0)
看起来你的dup在date_created列中有区别,所以你可以使用windowing函数捕获除了重复集的第一行以外的所有值,然后用它来删除额外的行
delete from foo
using
(select i_id, term, date_created
from (
select foo.*
, row_number() over (partition by i_id, term order by date_created asc) the_rank
from foo
) ranked
where ranked.the_rank <> 1
) extras
where foo.i_id = extras.i_id and foo.term = extras.term and foo.date_created = extras.date_created;
这与欧文的回答大致相似。它在选择要保留的最旧条目而不是最新条目方面有所不同,可以通过在排序子查询中将ASC从ASC更改为DESC来更改。