我准备了sql小提琴:http://sqlfiddle.com/#!15/62e65/2
架构就在这里:
CREATE TABLE products
("id" int, "name" varchar(5))
;
INSERT INTO products
("id", "name")
VALUES
(1, 'Car'),
(2, 'Phone')
;
CREATE TABLE operations
("id" int, "product_id" int, "status" varchar(7), "type" varchar(8))
;
INSERT INTO operations
("id", "product_id", "status", "type")
VALUES
(1, 1, 'pending', 'invoice'),
(2, 1, 'done', 'delivery'),
(3, 2, 'done', 'delivery'),
(3, 2, 'done', 'invoice')
;
我知道数据架构可能更好,但我现在没有可能重构它 - 我只是添加新视图。 关于架构的注意事项:产品总是有2个操作:开票和交货。 我想要达到的目的是获得这样的结果:
name status
car pending
phone done
产品状态是检查两个产品操作后返回的字符串 规则是产品状态仅在两个操作完成时完成,否则其待定 如何在postgres中编写这样的查询?
答案 0 :(得分:1)
SELECT p.name, CASE WHEN status='done' THEN 'done' else 'pending' END
FROM (
SELECT p.id, p.name, string_agg(distinct o.status, '') as status
FROM products p JOIN operations o ON o.product_id = p.id
GROUP BY p.id, p.name
) sub
我们在一个字符串(string_agg
)中连接不同的值,然后在主查询中检查:如果ne string是单'done'
,那么所有操作都是'done'
。否则,一个或两个操作都是'pending'
。
由于您的外键是products.id <--> operations.product_id
,我们必须GROUP BY
products.id
。
答案 1 :(得分:0)
select
p.name,
case
when count(case when status <> 'done' then 1 else null end) = 0 then 'done'
else 'pending'
end status
from products p
inner join operations o on p.id = o.product_id
group by p.name, p.id;
答案 2 :(得分:0)
您可以创建两个子查询,一个用于订单,一个用于交付,加入它们,然后使用case
表达式检查两者的状态:
SELECT invoice.name,
CASE WHEN invoice.status = 'done' and delivery.status = 'done' THEN 'done'
ELSE 'pending'
END AS status
FROM (SELECT p.name, p.id, o.status
FROM products p
JOIN operations o ON o.type = 'invoice' AND
o.product_id = p.id) invoice
JOIN (SELECT p.name, p.id, o.status
FROM products p
JOIN operations o ON o.type = 'delivery' AND
o.product_id = p.id) delivery
ON invoice.id = delivery.id