【问题标题】:Removing duplicates from multiple self left joins从多个自左连接中删除重复项
【发布时间】:2011-05-13 15:57:34
【问题描述】:

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

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

但不是两者兼而有之。

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

【问题讨论】:

    标签: sql optimization duplicates join duplicate-removal


    【解决方案1】:

    您需要在结果中添加一个订单才能过滤掉所有重复项。这可以通过确保a<b<c 来实现。一旦你的结果中有一个顺序,你就可以对结果集应用一个 distinct。

    ` 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

    和...`

    【讨论】:

      【解决方案2】:

      很难准确理解您想要实现的目标,但为了避免 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 ...
      

      这样,答案总是有序的

      【讨论】:

      • 感谢您的回复。重要的是每行中的数据(组合)不同而不是顺序。
      • 如果 A-B-C 与 C-B-A 相同,比较它们的唯一方法是将它们都表示为 A-B-C(或者我可能还缺少一些东西)。你能否举一个具体的例子来说明你想要达到的目标(使用一些真实的数据)?
      • 这和我的回答一样吗?
      • @kirk boradhurst 是的,很好,但是当我开始输入我的答案时,你的答案并不存在。伟大的思想都一样。
      【解决方案3】:

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

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

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

      【讨论】:

      • 感谢您的回复。我仍在努力解决这个问题,而您的答案是我已经尝试过的。不幸的是,它似乎删除了一些我目前无法解释的有效组合。可能是我上面没有列出的连接条件的结果。将继续进行实验。
      • 我会给你答案,因为你是第一个建议订购套装的人。干杯。
      【解决方案4】:

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

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

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

      【讨论】:

      • 感谢您的回复。可惜符号数量不小,对速度有需求!
      • 如果您对速度有要求,那么您应该考虑在此处对数据进行非规范化处理。这将使您能够更快地获取数据,但您必须为此付出一些设计开销。打破规范化以实现速度可能是一个有效的选择。您也可以考虑添加一个“Rule_ID”,这样所有规则都将映射到一个规则集。
      猜你喜欢
      • 1970-01-01
      • 2013-01-14
      • 2014-07-21
      • 2019-08-26
      • 2017-07-02
      • 2021-03-20
      • 2012-10-03
      • 2015-03-15
      • 1970-01-01
      相关资源
      最近更新 更多