我想用下表来计算z:

item value
a 6
b 8
group source_item weighting
x a 1
x b 0.25
y a 1
group source_group weighting
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

这将按如下方式返回订单:

group iteration
x 1
y 2
z 3

从这里开始,我计划使用另一棵递归树来遍历迭代并计算值.但是,由于您只能连接到最后一次递归,因此当您达到z时,x的值是不可访问的.我可能会在每次递归中提取所有的值,并在iteration + 1上做一些联接,以确保循环适当地结束,但我开始感觉到这不可能是做事情的"正确"方式.

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

推荐答案

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

只需从总数groups_itemsitems开始,然后递归超过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<>fiddle

Sql相关问答推荐

在数据分区内执行确定

具有2个共享列的两个表的Amazon RSQL合并

SQL查询组类值在同一行中,并连接和排序其他值

在postgres中动态计算出现次数并插入到json中

仅在特定字符串之后提取两个圆括号之间的计量单位文本

PostgreSQL使用SQL子查询在时间间隔内 Select 数据

从字符串中删除";1、";和";2,";,而不删除";11、";和";12、";

找到最新的连线

使用与JOIN一起使用的查询后进行分页和排序

如何在多列上编写具有不同条件的查询?

如何根据几个条件 Select 值:如果满足一个范围的SUM,则对另一个范围求和

使用 union 的有序结果获取行数

返回给定日期后的第 4 个工作日(不包括公众假期)

Oracle SQL:通过将日期与另一个表行进行比较来 Select 值

如何从postgresql中的项目映射(关联数组)设置值?

在Snowflake中如何使用SQL对版本字符串进行排序?

COBOL\DB2作业(job)需要帮助?快来获取专业指导!

如何获得上个月和下个月之间的销售额差异

SQL:如何从时间戳数据生成时间序列并计算不同事件类型的累计总和?

在 PostgreSQL 中,如何将数组中的每个元素用作另一个表中的键?