【问题标题】:Calculate total price with 'WITH RECURSIVE'使用“带递归”计算总价
【发布时间】:2015-11-02 12:49:45
【问题描述】:

我有一张“Leistung”表(意思是英语活动)和一张表,用于匹配给定数量的两项活动(benoetigt)。因此,例如 ID 为 2 的活动需要三个 ID 为 3 的活动。

每个活动(leistung)都有一个价格。

我现在想计算所有活动 (leistung) 的总价格,包括正确数量的子活动的价格。

这是我的一些测试数据表:

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 Fiddle:SQL Fiddle

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

对于上面的测试数据,结果应如下所示:

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。此外,此活动需要 12 个 ID 为 6 的活动(成本为 20)(根据 ' 中的第一个条目benoetigt')。

总之:50 + 12*20 = 290

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

【问题讨论】:

  • 该数据的期望输出是什么?
  • 用所需的输出更新了问题以及为什么它不是重复的。到目前为止,谢谢。

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


【解决方案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

【讨论】:

    猜你喜欢
    • 2021-05-16
    • 2020-07-04
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多