找到重复的组合

时间:2015-11-15 11:39:06

标签: sql postgresql duplicates aggregate-functions

我需要一个查询来查找这些表中的重复组合:

的AttributeValue:

 id | name
------------------
  1 | green
  2 | blue
  3 | red
  4 | 100x200
  5 | 150x200

产品:

 id | name
----------------
 1  | Produkt A

ProductAttribute:

 id | id_product | price
--------------------------
  1 |          1 |   100
  2 |          1 |   200
  3 |          1 |   100
  4 |          1 |   200
  5 |          1 |   100
  6 |          1 |   200
  7 |          1 |   100   -- duplicate combination
  8 |          1 |   100   -- duplicate combination

ProductAttributeCombinations:

 id_product_attribute | id_attribute
-------------------------------------
                    1 |           1
                    1 |           4
                    2 |           1
                    2 |           5
                    3 |           2
                    3 |           4
                    4 |           2
                    4 |           5
                    5 |           3
                    5 |           4
                    6 |           3
                    6 |           5
                    7 |           1
                    7 |           4
                    8 |           1
                    8 |           5

我需要创建结果的SQL,如:

id_product | duplicate_attributes
----------------------------------
         1 | {7,8}    

2 个答案:

答案 0 :(得分:0)

如果我理解正确,7是1的重复,8是2的副本。如上所述,你的问题有点令人困惑,因为7和8彼此无关,唯一感兴趣的表是{ {1}}。

如果是这种情况,那么一种方法是使用字符串聚合

ProductAttributeCombinations

答案 1 :(得分:0)

你的问题留有一些解释空间。这是我受过教育的猜测:

对于每个产品,返回具有与具有较小ID的同一产品的任何其他实例相同的属性集的所有实例的数组。

WITH combo AS (
   SELECT id_product, id, array_agg(id_attribute) AS attributes
   FROM  (
      SELECT pa.id_product, pa.id, pac.id_attribute
      FROM   ProductAttribute            pa
      JOIN   PoductAttributeCombinations pac ON pac.id_product_attribute = pa.id
      ORDER  BY pa.id_product, pa.id, pac.id_attribute
      ) sub
   GROUP  BY 1, 2
   )
SELECT id_product, array_agg(id) AS duplicate_attributes
FROM   combo c
WHERE  EXISTS (
   SELECT 1
   FROM   combo
   WHERE  id_product = c.id_product
   AND    attributes = c.attributes
   AND    id < c.id
   )
GROUP  BY 1;

排序可以内联到聚合函数中,因此我们不需要用于排序的子查询(like @Gordon already provided)。这个更短,但通常也更慢:

WITH combo AS (
   SELECT pa.id_product, pa.id
        , array_agg(pac.id_attribute ORDER BY pac.id_attribute) AS attributes
   FROM   ProductAttribute            pa
   JOIN   PoductAttributeCombinations pac ON pac.id_product_attribute = pa.id
   GROUP  BY 1, 2
   )
SELECT ...

这只返回具有重复实例的产品。

SQL Fiddle.

你的表名相当误导/与你提出的其他问题相矛盾。您的示例数据也不是很清晰,只有产品。我假设你的桌子上有很多。

目前还不清楚你是否使用保留CaMeL-case拼写的双引号表名。我假设:不。