使用来自不同深度的嵌套组的值执行计算的干净方法?

问题描述 投票:0回答:1

我想使用下表来计算z

项目 价值
a 6
b 8
来源_项目 加权
x a 1
x b 0.25
y a 1
来源_组 加权
y x 0.5
z x 1
z y 1

作为人类,我会通过计算来解决:

x = 1a + 0.25b = 8

y = 1a + 0.5x = 10

z = 1x + 1y = 18

然而,我正在努力寻找一种在 SQL 中执行此操作的干净方法。

通过使用递归 CTE,我可以相当轻松且(我希望)干净地获得操作顺序 - 如下:

WITH RECURSIVE
    iterations AS (
        --start by getting the groups that aren't dependent on other groups
        SELECT
            g.group
            , 1 AS iteration
        FROM
            groups AS g
            LEFT JOIN groups_groups AS gg
                ON gg.source_group = g.group
        WHERE
            gg.source_group IS NULL
        --traverse dependencies upwards
        UNION ALL
            SELECT
                gg.group
                , i.iteration + 1 AS iteration
            FROM
                iterations AS i
                LEFT JOIN groups_groups AS gg
                    ON gg.source_group = i.group
    )
--filter to max iteration
SELECT DISTINCT
    i.group
    , MAX(i.iteration) OVER (PARTITION BY i.group) AS iteration
FROM
    iterations AS i
ORDER BY
    iteration

这将返回订单如下:

迭代
x 1
y 2
z 3

从这里开始,我计划使用另一个递归树来进行迭代并计算值。但是,由于您只能加入最后一个递归,因此当您到达 z 时,x 的值将无法访问。我可能可以通过每次递归提取所有值,并在

iteration + 1
上进行一些连接,以确保循环适当结束,但我开始感觉到这不可能是“正确”的做事方式。

有没有更简单、更干净等的方法来解决这个问题?

sql postgresql recursive-query recursive-cte
1个回答
0
投票

我觉得你想多了。您不需要知道操作顺序(除非涉及括号)。

首先计算

groups_items
items
的总和,然后递归
groups_groups
,最后将总和加到
group

WITH RECURSIVE cte AS (
    SELECT
      gi."group",
      SUM(i.value * gi.weighting) AS total
    FROM groups_items gi
    JOIN items i ON i.item = gi.source_item
    GROUP BY
      gi."group"

    UNION ALL

    SELECT
      gg."group",
      cte.total * gg.weighting AS total
    FROM cte
    JOIN groups_groups gg ON gg.source_group = cte."group"
)
SELECT
  cte."group",
  SUM(cte.total) AS total
FROM cte
GROUP BY
  cte."group";

db<>小提琴

© www.soinside.com 2019 - 2024. All rights reserved.