我有一个描述实体之间关系的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]
都不重要。
我觉得这里有一个简单的解决方案,但它正在逃避我。
答案 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
。