Isso manterá uma das duplicatas:
delete from join_table
where ctid not in (select min(ctid)
from join_table
group by id1, id2);
Sua tabela não possui um identificador exclusivo que possa ser usado para "escolher um sobrevivente". É aí que o
ctid
do Postgres é útil, pois é um identificador interno exclusivo para cada linha. Observe que você nunca deve usar o ctid
para mais do que apenas uma única declaração. Não é uma coisa universalmente única, mas para o tempo de execução de uma única instrução, está tudo bem. Exemplo do SQLFiddle:http://sqlfiddle.com/#!15/dabfc/1
Se você quiser se livrar de todos linhas duplicadas:
delete from join_table
where (id1, id2) in (select id1, id2
from join_table
group by id1, id2
having count(*) > 1);
Nenhuma das soluções será rápida em uma mesa grande. Criar uma nova tabela sem duplicatas como o jjanes mostrou será muito mais rápido se você precisar de um número substancial de linhas de uma tabela grande.