用 '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