尝试以不同方式多次选择同一列。如何改善查询?

问题描述 投票:1回答:1

我正在尝试获取与每个产品相关的类别数组,然后在另一列中获得每个产品的顶级父类别,根据我的逻辑,这是为Categories数组找到相同的值,但只能选择parent_id为NULL,每个id仅应拉回一个值和1条记录。我真的不知道构造此查询的最佳方法。我有什么工作,但是对于具有父ID的类别,它还在父类别列中显示NULL值,并且为每个产品创建了第二条记录,因为我被迫将其放在分组依据中。基本上,我只是认为我没有以正确或最有效的方式执行此操作。

如果我不清楚,请告诉我。

我希望结果集如何显示:

+----+----------------+------------------+------------------------------------------------+------------------+
| id | name           | category_ids     | category_names                                 | parent_category  |
+----+----------------+------------------+------------------------------------------------+------------------+
| 1  | Product Name 1 | {111,222,333}    | {Electronics, computers, computer accessories} | Electronics      |
+----+----------------+------------------+------------------------------------------------+------------------+

我当前的查询(不理想):

select p.id, 
p.name, 
array_agg(category_id) as category_ids,
regexp_replace(array_agg(c.name)::text,'"|''','','gi') as category_names,
c1.name as parent_category
from products p
join product_categorizations pc
on pc.product_id = p.id
join categories c
on pc.category_id = c.id
full outer join (select name, id from categories where parent_id is null and name is not null) c1
on c.id = c1.id
group by 1,2,5;

+----+----------------+------------------+-----------------------------------+------------------+
| id | name           | category_ids     | category_names                    | parent_category  |
+----+----------------+------------------+-----------------------------------+------------------+
| 1  | Product Name 1 | {111}            | {Electronics}                     | Electronics      |
+----+----------------+------------------+-----------------------------------+------------------+
| 1  | Product Name 1 | {222,333}        | {computers, computer accessories} | NULL             |
+----+----------------+------------------+-----------------------------------+------------------+
sql postgresql
1个回答
0
投票

用聚合的FULL JOIN子句替换FILTER

SELECT p.id
     , p.name
     , array_agg(pc.category_id) AS category_ids
     , string_agg(c.name, ', ')  AS category_names  -- regexp_replace .. ?
     , min(c.name) FILTER (WHERE c.parent_id IS NULL) AS parent_category
FROM   products                p
JOIN   product_categorizations pc ON pc.product_id = p.id
JOIN   categories              c  ON pc.category_id = c.id
GROUP  BY p.id;

参见:

((为什么要添加AND name IS NOT NULL?无论如何,min()都会忽略NULL值。)

虽然汇总了[[all产品,并且在强制执行参照完整性的同时,这应该快一些:

SELECT p.name, pc.* FROM products p JOIN ( SELECT pc.product_id AS id , array_agg(pc.category_id) AS category_ids , string_agg(c.name, ', ') AS category_names , min(c.name) FILTER (WHERE c.parent_id IS NULL) AS parent_category FROM product_categorizations pc JOIN categories c ON pc.category_id = c.id GROUP BY 1 ) pc USING (id);
关键是product仅联接

after

聚集行。此外:“名称”不是很有用的列名称。相关:

© www.soinside.com 2019 - 2024. All rights reserved.