使用'WITH RECURSIVE'计算总价

时间:2015-11-02 12:49:45

标签: sql postgresql common-table-expression recursive-query

我有一个表'Leistung'(这意味着英语活动)和一个用于两个活动与给定数量(benoetigt)之间的匹配。因此,例如ID为2的活动需要三个ID为3的活动。

每项活动(leistung)都有价格。

我现在想要计算所有活动(leistung)的总价,包括适当数量的儿童活动的价格。

以下是我的表格,其中包含一些testdata:

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;

但我不知道如何将此结果与活动的定价联系起来。

或者这是错误的尝试?

以下是来自testdata的SQL小提琴,以便更好地理解:SQL Fiddle

编辑:所需的输出是一个列表,其中包含所有活动的总价格,包括他们孩子的价格。

对于上面的testdata,结果应如下所示:

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'的活动的总价格为290,因为活动本身需要花费50.此活动还需要ID为6的12个活动(费用为20)(根据'中的第一项) benoetigt')。

总结:50 + 12 * 20 = 290

在重复标记的问题中,递归仅发生在一个表中。但我有问题,价格信息在另一个表格中。

1 个答案:

答案 0 :(得分:1)

现在您需要将递归CTE的结果与您的活动表一起加入两次(一次加入以获得父级价格,另一次加入以获得子活动的价格)和按父活动分组,总结儿童活动的费用:

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