我正在尝试获取与每个产品相关的类别数组,然后在另一列中获得每个产品的顶级父类别,根据我的逻辑,这是为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 |
+----+----------------+------------------+-----------------------------------+------------------+
用聚合的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