我试图写一个相当简单的PSQL查询来检索一些数据(我意识到它现在不是最有效的查询):
SELECT c.name AS article, c.id AS article_id, t.name AS template, t.id AS template_id, brand_names, COUNT(p.component_id)
FROM publications p
INNER JOIN components c
(SELECT string_agg(b.name, ', ') AS brand_names
FROM brands b
INNER JOIN brands_components
ON b.id = brands_components.brand_id
WHERE brands_components.component_id = c.id
) brand_query
ON c.id = p.component_id
INNER JOIN brands_components bc
ON c.id = bc.component_id
AND bc.brand_id IN (16, 23, 24, 35, 37)
INNER JOIN components_templates ct
ON c.id = ct.component_id
INNER JOIN templates t
ON t.id = ct.template_id
这在第4行给出了语法错误。缺少什么?如果我单独运行子查询,它可以正常工作:
语法错误在或附近" SELECT"第4行:( SELECT string_agg(b.name,',')AS brand_names ^:SELECT c.name AS article,c.id AS article_id,t.name AS template,t.id AS template_id, brand_nam
子查询旨在检索每个组件的所有品牌名称,并将其显示在一行而不是多行中。他们的联接表是brands_components
。
可用的小提琴here,所需的结果应该是:
article article_id template template_id count brands
--------------------------------------------------------------------------------------------------------------
component one | 1 | template one | 1 | 4 | brand one, brand two, brand three, brand four
答案 0 :(得分:4)
通过横向连接可以解决您的直接问题:
SELECT c.name AS article, c.id AS article_id, t.name AS template, t.id AS template_id, brand_names, COUNT(p.component_id)
FROM publications p
JOIN components c ON c.id = p.component_id
JOIN brands_components bc ON c.id = bc.component_id AND bc.brand_id IN (1, 2, 3, 4)
JOIN LATERAL (
SELECT b.id, string_agg(b.name, ', ') AS brand_names
FROM brands b
JOIN brands_components ON b.id = brands_components.brand_id
WHERE brands_components.component_id = c.id
GROUP BY b.id
) brand_query ON brand_query.id = bc.brand_id
JOIN components_templates ct ON c.id = ct.component_id
JOIN templates t ON t.id = ct.template_id
GROUP BY 1,2,3,4
由于group by
不包含brand_names
列,因此仍然无法运行。 Postgres不知道brand_names
已经是聚合。
但是,如果将聚合移动到外部查询,则不需要派生表:
SELECT c.name AS article,
c.id AS article_id,
t.name AS template,
t.id AS template_id,
string_agg(b.name, ',') as brand_names,
COUNT(p.component_id)
FROM publications p
JOIN components c ON c.id = p.component_id
JOIN brands_components bc ON c.id = bc.component_id AND bc.brand_id IN (1, 2, 3, 4)
JOIN brands b on b.id = bc.brand_id
JOIN components_templates ct ON c.id = ct.component_id
JOIN templates t ON t.id = ct.template_id
GROUP BY c.name, c.id, t.name, t.id;
答案 1 :(得分:3)
尝试此查询:
SELECT c.name AS article, c.id AS article_id, t.name AS template, t.id AS template_id,MAX(brand_names) AS brand_names, COUNT(p.component_id) AS Counts
FROM publications p
INNER JOIN components c
ON c.id = p.component_id
INNER JOIN brands_components bc
ON c.id = bc.component_id
AND bc.brand_id IN (1, 2, 3, 4)
INNER JOIN components_templates ct
ON c.id = ct.component_id
INNER JOIN templates t
ON t.id = ct.template_id
INNER JOIN (SELECT string_agg(b.name, ', ') AS brand_names
FROM brands b
INNER JOIN brands_components bcc
ON b.id = bcc.brand_id
INNER JOIN components c ON bcc.component_id = c.id
) brand_query ON brand_names IS NOT NULL
Group by c.name,c.id,t.name,t.id
答案 2 :(得分:1)
我用working获得了一个函数:
CREATE FUNCTION brands(int) RETURNS varchar AS $$
SELECT string_agg(b.name, ', ') AS brand_names
FROM brands b
INNER JOIN brands_components
ON b.id = brands_components.brand_id
WHERE brands_components.component_id = $1
$$ LANGUAGE SQL;
SELECT c.name, c.id, t.name AS template_name, t.id AS template_id, brands(c.id), COUNT(p.component_id)
FROM publications p
INNER JOIN components c
ON c.id = p.component_id
INNER JOIN brands_components bc
ON c.id = bc.component_id
AND bc.brand_id IN (1, 2, 3, 4)
INNER JOIN components_templates ct
ON c.id = ct.component_id
INNER JOIN templates t
ON t.id = ct.template_id
GROUP BY 1, 2, 3, 4
不确定哪个更可取,但它可能是DineshDB的。