3

我正在动态生成如下所示的查询,该查询通过在自身上左连接(任意次数)来创建不同的规则组合,并避免具有某些相同属性的规则作为连接条件的一部分,例如

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

4 回答 4

4

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

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

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

于 2010-11-22T06:46:44.987 回答
3

我认为您的意思是要从行排列变为组合行?

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

如果符号的数量很少,您可以通过在索引 1 中插入“A”,在索引 2 中插入“B”等,将它们插入预先排序的数组中。这可能会更快......

于 2010-11-22T06:21:55.883 回答
2

您需要在结果中排​​序以过滤掉所有重复项。这可以通过确保a<b<c. 一旦你的结果中有一个顺序,你就可以对结果集应用不同的顺序。

` SELECT count(*) FROM 规则 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 < t2.id 和 t2.id < t3.id ...

和...`

于 2010-11-22T17:57:38.657 回答
1

很难准确理解你想要达到的目标,但为了避免 ABC CBA 重复,试试这个:

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 ...

这样,答案总是有序的

于 2010-11-22T08:18:57.113 回答