通过可能的重复名称排序id不同

时间:2015-08-23 13:30:59

标签: sql postgresql distinct

我对查询有以下要求:

  • 需要在内部联接表上订购(请参阅下面的from_products_products),
  • 允许from_products_products
  • 上的重复名称
  • 它不能在原始表上返回重复记录(products.id上的不同)。

以下查询将消除重复的名称,这是不可取的,因为我必须在from_products_products.name上使用order by,因为SELECT DISTINCT ON (from_products_products.name, products.id) "products".* FROM "products" INNER JOIN "suppliers_plugin_source_products" ON "suppliers_plugin_source_products"."to_product_id" = "products"."id" INNER JOIN "products" "from_products_products" ON "from_products_products"."id" = "suppliers_plugin_source_products"."from_product_id" INNER JOIN "suppliers_plugin_source_products" "sources_from_products_products_join" ON "sources_from_products_products_join"."to_product_id" = "products"."id" INNER JOIN "suppliers_plugin_suppliers" ON "suppliers_plugin_suppliers"."id" = "sources_from_products_products_join"."supplier_id" WHERE "products"."profile_id" = 45781 AND (("products"."type" IN ('SuppliersPlugin::DistributedProduct') OR "products"."type" IS NULL)) AND (products.archived <> true) ORDER BY from_products_products.name ASC, products.id 中使用了

GROUP BY

使用products具有相同的效果,也不会删除重复项;

INNER JOIN与任何产品不匹配时提供重复SELECT "products".* FROM "products" INNER JOIN "suppliers_plugin_source_products" ON "suppliers_plugin_source_products"."to_product_id" = "products"."id" INNER JOIN "products" "from_products_products" ON "from_products_products"."id" = "suppliers_plugin_source_products"."from_product_id" INNER JOIN "suppliers_plugin_source_products" "sources_from_products_products_join" ON "sources_from_products_products_join"."to_product_id" = "products"."id" INNER JOIN "suppliers_plugin_suppliers" ON "suppliers_plugin_suppliers"."id" = "sources_from_products_products_join"."supplier_id" WHERE "products"."profile_id" = 45781 AND (("products"."type" IN ('SuppliersPlugin::DistributedProduct') OR "products"."type" IS NULL)) AND (products.archived <> true) ORDER BY from_products_products.name ASC 的原始查询:

->

那么,如何在PostgreSQL上克服这个问题?

PS:这是开源软件Noosfero-ecosol的一部分

2 个答案:

答案 0 :(得分:1)

这样做你想要的吗?

with t as (
    SELECT DISTINCT ON (products.id) "products".*,
           from_products_products.name as from_products_name
    FROM "products" 
      INNER JOIN "suppliers_plugin_source_products" ON "suppliers_plugin_source_products"."to_product_id" = "products"."id"
      INNER JOIN "products" "from_products_products" ON "from_products_products"."id" = "suppliers_plugin_source_products"."from_product_id"
      INNER JOIN "suppliers_plugin_source_products" "sources_from_products_products_join" ON "sources_from_products_products_join"."to_product_id" = "products"."id"
      INNER JOIN "suppliers_plugin_suppliers" ON "suppliers_plugin_suppliers"."id" = "sources_from_products_products_join"."supplier_id"
      WHERE "products"."profile_id" = 45781 AND (("products"."type" IN ('SuppliersPlugin::DistributedProduct') OR "products"."type" IS NULL)) AND (products.archived <> true)
      ORDER BY products.id
     )
select t.*
from t
order by from_products_name

它似乎符合您的要求。

编辑:

如果上面做了你想要的,我可以想到五个选择:

  • 以上使用CTE。
  • 基本相同的逻辑,使用子查询。
  • 使用窗口函数,结构非常相似。
  • 使用group by
  • 使用where子句进行过滤逻辑。

以下是group by方法:

    SELECT "products".*,
           MIN(from_products_products.name) as from_products_name
    FROM "products" 
      INNER JOIN "suppliers_plugin_source_products" ON "suppliers_plugin_source_products"."to_product_id" = "products"."id"
      INNER JOIN "products" "from_products_products" ON "from_products_products"."id" = "suppliers_plugin_source_products"."from_product_id"
      INNER JOIN "suppliers_plugin_source_products" "sources_from_products_products_join" ON "sources_from_products_products_join"."to_product_id" = "products"."id"
      INNER JOIN "suppliers_plugin_suppliers" ON "suppliers_plugin_suppliers"."id" = "sources_from_products_products_join"."supplier_id"
      WHERE "products"."profile_id" = 45781 AND (("products"."type" IN ('SuppliersPlugin::DistributedProduct') OR "products"."type" IS NULL)) AND (products.archived <> true)
      GROUP BY products.id
      ORDER BY from_products_name;

此表单取决于products.id被声明为主键。或者,您可以将该表中的所有列放在group by

答案 1 :(得分:1)

重写(简化别名)会产生:

SELECT p1.*
FROM products p1
INNER JOIN suppliers_plugin_source_products spsp
        ON spsp.to_product_id = p1.id
INNER JOIN products p2
        ON p2.id = spsp.from_product_id
INNER JOIN suppliers_plugin_source_products spsp2
        ON spsp2.to_product_id = p1.id -- <<-- Huh?
INNER JOIN suppliers_plugin_suppliers sps
        ON sps.id = spsp2.supplier_id
WHERE p1.profile_id = 45781
  AND (p1."type" IN ('SuppliersPlugin::DistributedProduct') OR p1."type" IS NULL)
  AND p1.archived <> true
ORDER BY p2.name ASC -- <<-- Huh?
    ;

外部查询仅引用产品表p1和p2。 假设加入&#34; suppliers_plugin_source_products&#34;表格两次是无意的,这可以简化为:

SELECT p1.*
FROM products p1
JOIN products p2
  ON EXISTS (
    SELECT * FROM suppliers_plugin_source_products spsp
    -- the next line might not be necessary ...
    INNER JOIN suppliers_plugin_suppliers sps ON sps.id = spsp.supplier_id
    WHERE spsp.to_product_id = p1.id
    AND spsp.from_product_id = p2.id
    )
WHERE p1.profile_id = 45781 
  AND (p1."type" IN ('SuppliersPlugin::DistributedProduct') OR p1."type" IS NULL)
  AND p1.archived <> true
ORDER BY p2.name ASC
    ;                         
相关问题