用 'WITH RECURSIVE' 计算总价
Calculate total price with 'WITH RECURSIVE'
我有一个 table 'Leistung'(英文的意思是 activity),还有一个用于两个 activity 之间给定数量的匹配 (benoetigt)。例如,ID 为 2 的 activity 需要三个 ID 为 3 的 activity。
每个 activity (leistung) 都有一个价格。
我现在想计算所有 activitys (leistung) 的总价,包括来自 child activitys 的正确数量的价格。
这是我的 tables 和一些测试数据:
CREATE TABLE Leistung (
lnr INTEGER PRIMARY KEY,
bezeichnung VARCHAR(100) NOT NULL,
price NUMERIC(7,2) NOT NULL
);
CREATE TABLE benoetigt (
lnr INTEGER REFERENCES Leistung(lnr),
benoetigt_lnr INTEGER REFERENCES Leistung(lnr),
amount INTEGER NOT NULL,
PRIMARY KEY (lnr,benoetigt_lnr)
);
INSERT INTO Leistung(lnr, bezeichnung, price) VALUES
(1, 'Discokugel', 100),
(2, 'Strobolicht', 100),
(3, 'Verstärker', 90),
(4, 'Gelaender',50),
(5, 'Bühne',50),
(6, 'Bühnenelement',20),
(7, 'Stromverteiler', 40),
(8, 'Stromkabel', 20);
INSERT INTO benoetigt (lnr, benoetigt_lnr, amount) VALUES
(5,6,12),
(1,7,1),
(2,7,1),
(7,8,1);
我很确定该解决方案仅适用于 'WITH RECURSIV' 查询。
我的第一次尝试是这样的:
WITH RECURSIVE benoetigtlist(lnr,benoetigt_lnr,menge) AS (
SELECT lnr, benoetigt_lnr, menge FROM benoetigt
UNION ALL
SELECT b.lnr, b.benoetigt_lnr, b.menge
FROM benoetigtlist bl, benoetigt b
WHERE b.lnr = bl.benoetigt_lnr
)
SELECT * FROM benoetigtlist;
但我不知道如何使这个结果与 activity 的定价之间的 link。
或者这是错误的尝试?
这里有一个来自测试数据的 SQL Fiddle 以便更好地理解:SQL Fiddle
编辑:所需的输出是一个列表,其中包含所有 activity 的总价,包括其 children 的价格。
对于上面的测试数据,结果应该如下所示:
id text price
1 'Discokugel' 160 // 100 + 1*40 + 1*20
2 'Strobolicht' 160 // 100 + 1*40 + 1*20
3 'Verstärker' 90
4 'Gelaender' 50
5 'Bühne' 290 // 50 + 12*20
6 'Bühnenelement' 20
7 'Stromverteiler' 60 // 40 + 1*20
8 'Stromkabel' 20
例如ID为5'Bühne'的activity总价为290,因为activity本身要50,另外这个activity需要12activitys of ID 6(花费 20)(根据 'benoetigt' 中的第一个条目)。
总结:50 + 12*20 = 290
在标记为重复的问题中,递归只发生在一个 table 中。但我的问题是价格信息在另一个 table.
现在您需要将递归 CTE 的结果与 activity table 连接两次(一次连接获取 parent 的价格,另一次连接获取 child activity) 并按 parent activity 分组,总结 child 活动的成本:
WITH RECURSIVE benoetigtlist(lnr,benoetigt_lnr,menge) AS (
SELECT lnr, benoetigt_lnr, amount
FROM benoetigt
UNION ALL
SELECT bl.lnr, b.benoetigt_lnr, b.amount
FROM benoetigtlist bl
, benoetigt b
WHERE b.lnr = bl.benoetigt_lnr
)
SELECT parent.lnr
, parent.bezeichnung
-- replace null with 0 if there are no child activities
, parent.price + COALESCE(children_cost.cost, 0) AS cost
FROM Leistung parent
-- subquery that summarizes total cost of all children:
LEFT JOIN (
SELECT bl.lnr, SUM(bl.menge * l.price) as cost
FROM benoetigtlist bl
INNER JOIN Leistung l on bl.benoetigt_lnr = l.lnr
GROUP BY bl.lnr
) children_cost ON children_cost.lnr = parent.lnr
ORDER BY parent.lnr
我有一个 table 'Leistung'(英文的意思是 activity),还有一个用于两个 activity 之间给定数量的匹配 (benoetigt)。例如,ID 为 2 的 activity 需要三个 ID 为 3 的 activity。
每个 activity (leistung) 都有一个价格。
我现在想计算所有 activitys (leistung) 的总价,包括来自 child activitys 的正确数量的价格。
这是我的 tables 和一些测试数据:
CREATE TABLE Leistung (
lnr INTEGER PRIMARY KEY,
bezeichnung VARCHAR(100) NOT NULL,
price NUMERIC(7,2) NOT NULL
);
CREATE TABLE benoetigt (
lnr INTEGER REFERENCES Leistung(lnr),
benoetigt_lnr INTEGER REFERENCES Leistung(lnr),
amount INTEGER NOT NULL,
PRIMARY KEY (lnr,benoetigt_lnr)
);
INSERT INTO Leistung(lnr, bezeichnung, price) VALUES
(1, 'Discokugel', 100),
(2, 'Strobolicht', 100),
(3, 'Verstärker', 90),
(4, 'Gelaender',50),
(5, 'Bühne',50),
(6, 'Bühnenelement',20),
(7, 'Stromverteiler', 40),
(8, 'Stromkabel', 20);
INSERT INTO benoetigt (lnr, benoetigt_lnr, amount) VALUES
(5,6,12),
(1,7,1),
(2,7,1),
(7,8,1);
我很确定该解决方案仅适用于 'WITH RECURSIV' 查询。 我的第一次尝试是这样的:
WITH RECURSIVE benoetigtlist(lnr,benoetigt_lnr,menge) AS (
SELECT lnr, benoetigt_lnr, menge FROM benoetigt
UNION ALL
SELECT b.lnr, b.benoetigt_lnr, b.menge
FROM benoetigtlist bl, benoetigt b
WHERE b.lnr = bl.benoetigt_lnr
)
SELECT * FROM benoetigtlist;
但我不知道如何使这个结果与 activity 的定价之间的 link。
或者这是错误的尝试?
这里有一个来自测试数据的 SQL Fiddle 以便更好地理解:SQL Fiddle
编辑:所需的输出是一个列表,其中包含所有 activity 的总价,包括其 children 的价格。
对于上面的测试数据,结果应该如下所示:
id text price
1 'Discokugel' 160 // 100 + 1*40 + 1*20
2 'Strobolicht' 160 // 100 + 1*40 + 1*20
3 'Verstärker' 90
4 'Gelaender' 50
5 'Bühne' 290 // 50 + 12*20
6 'Bühnenelement' 20
7 'Stromverteiler' 60 // 40 + 1*20
8 'Stromkabel' 20
例如ID为5'Bühne'的activity总价为290,因为activity本身要50,另外这个activity需要12activitys of ID 6(花费 20)(根据 'benoetigt' 中的第一个条目)。
总结:50 + 12*20 = 290
在标记为重复的问题中,递归只发生在一个 table 中。但我的问题是价格信息在另一个 table.
现在您需要将递归 CTE 的结果与 activity table 连接两次(一次连接获取 parent 的价格,另一次连接获取 child activity) 并按 parent activity 分组,总结 child 活动的成本:
WITH RECURSIVE benoetigtlist(lnr,benoetigt_lnr,menge) AS (
SELECT lnr, benoetigt_lnr, amount
FROM benoetigt
UNION ALL
SELECT bl.lnr, b.benoetigt_lnr, b.amount
FROM benoetigtlist bl
, benoetigt b
WHERE b.lnr = bl.benoetigt_lnr
)
SELECT parent.lnr
, parent.bezeichnung
-- replace null with 0 if there are no child activities
, parent.price + COALESCE(children_cost.cost, 0) AS cost
FROM Leistung parent
-- subquery that summarizes total cost of all children:
LEFT JOIN (
SELECT bl.lnr, SUM(bl.menge * l.price) as cost
FROM benoetigtlist bl
INNER JOIN Leistung l on bl.benoetigt_lnr = l.lnr
GROUP BY bl.lnr
) children_cost ON children_cost.lnr = parent.lnr
ORDER BY parent.lnr