查询以从表中删除所有冗余条目

时间:2013-09-12 16:39:21

标签: postgresql

我有一个描述实体之间关系的Postgres表,这个表由一个我无法修改的进程填充。这是该表的一个示例:

+-----+-----+
| e1  | e2  |
|-----+-----|
|  A  |  B  |
|  C  |  D  |
|  D  |  C  |
| ... | ... |
+-----+-----+

我想编写一个SQL查询,它将从表中删除所有不必要的关系,例如,[D, C]关系是冗余的,因为它已由[C, D]定义。

我有一个使用自连接删除的查询,但这会删除与关系有关的所有内容,例如:

DELETE FROM foo USING foo b WHERE foo.e2 = b.e1 AND foo.e1 = b.e2;

结果:

+-----+-----+
| e1  | e2  |
|-----+-----|
|  A  |  B  |
| ... | ... |
+-----+-----+

但是,我需要一个可以让我了解其中一种关系的查询,无论哪种关系仍然存在,[C, D][D, C]都不重要。

我觉得这里有一个简单的解决方案,但它正在逃避我。

2 个答案:

答案 0 :(得分:2)

一般解决方案是使用始终唯一的伪列ctid

DELETE FROM foo USING foo b WHERE foo.e2 = b.e1 AND foo.e1 = b.e2
    AND foo.ctid > b.ctid;

顺便提一下,它保留了物理位置最接近表格第一个数据页面的元组。

答案 1 :(得分:1)

假设一个精确的重复行被约束,给定关系总会最多有两行:(C,D)和(D,C)在你的例子中。相同的约束也意味着两列具有不同的值:对(C,C)可能是合法的,但不能重复。

假设所涉及的数据类型具有明确的>定义,您可以添加一个条件,即要删除的行是第一列>第二列的行,并保留另一列不变。

在您的示例查询中,这意味着要添加AND foo.e1 > foo.e2