从多个自左连接中删除重复项

时间:2010-11-22 06:00:22

标签: sql optimization duplicates join duplicate-removal

我正在动态生成一个类似于下面的查询,通过左边连接(任意次数)创建不同的规则组合,并避免使用具有某些相同属性的规则作为连接条件的一部分,例如

SELECT count(*) 
FROM rules AS t1 
LEFT JOIN rules AS t2
 ON t1.id != t2.id
 AND ...
LEFT JOIN rules AS t3
 ON t1.id != t2.id AND t1.id != t3.id AND t2.id != t3.id
 AND ...

我目前正在删除重复项,方法是从已连接的行创建一个ID数组,然后按它们进行排序和分组:

SELECT sort(array[t1.id, t2.id, t3.id]) AS ids
...
GROUP BY ids

我想知道是否有更好的方法可以删除重复的行,例如

t1.ID | t2.ID | t3.ID
---------------------
  A   |   B   |   C
  C   |   B   |   A

应该是

t1.ID | t2.ID | t3.ID
---------------------
  A   |   B   |   C

或者

t1.ID | t2.ID | t3.ID
---------------------
  C   |   B   |   A

但不是两个。

编辑:我想从行的排列变为组合行。

4 个答案:

答案 0 :(得分:4)

我建议而不是加入!=,尝试加入< =。

然后,您将拥有t1.id>的所有组合。 t2.id,t2.id> t3.id,等等。

行不会是'重复',因为它们是有序集,任何包含等效成员的集都必然会产生相同的有序集。

答案 1 :(得分:3)

我认为你的意思是你想从行的排列变为组合行?

如果是这样,选择不同的答案是错误的。选择distinct将选择不同的排列。我认为你有一个非常好的方法。我唯一能想到的就是将规则连接成一个字符串并将其排序。看起来你正在使用Postgresql,并且没有内置字符串函数中的功能。

如果符号数量很小,您可以将它们插入到预先排序的数组中,方法是在索引1中插入'A',在索引2中插入'B'等等。这可能会更快排序......

答案 2 :(得分:2)

您需要在结果中获取订单,以便过滤掉所有重复项。这可以通过确保a<b<c来实现。一旦您的结果中有订单,您就可以对结果集应用不同的。

` SELECT count(*)FROM rules AS t1

LEFT JOIN规则AS t2 ON t1.id!= t2.id AND

LEFT JOIN规则AS t3 ON t1.id!= t2.id AND t1.id!= t3.id AND t2.id!= t3.id ......

t1.id&lt; t2.id和t2.id&lt; t3.id ...

AND ...`

答案 3 :(得分:1)

很难准确理解你想要实现的目标,但要避免A-B-C C-B-A重复,请试试这个:

SELECT count(*) 
FROM rules AS t1 
LEFT JOIN rules AS t2
 ON t1.id **<** t2.id
 AND ...
LEFT JOIN rules AS t3
 ON t1.id **<** t2.id AND t1.id **<** t3.id AND t2.id **<** t3.id
 AND ...

这样,答案总是有序的