简体   繁体   English

如何使用 sql 获取树中所有父母的孩子的累积总和?

[英]How to get cumulative sum of children for all parents in a tree using sql?

so I have a sql query to get the tree structure with unlimited depth as follows.所以我有一个 sql 查询来获取无限深度的树结构,如下所示。 But i'm clueless about getting the total for each parent.但我对获得每个父母的总数一无所知。

I have a table dimensionValue which has id, dimensionValueId, name I have another table valuation which has id, dimensionValue and volume.我有一个具有 id、dimensionValueId、名称的表 dimensionValue 我有另一个具有 id、dimensionValue 和 volume 的表评估。 The volume needs to be added at each parent level.需要在每个父级别添加卷。

I have http://sqlfiddle.com/#!15/5c0e7/5

I also want to get the flat sql with cumulative total, Currently I only have tree.我还想获得累积总数的平坦 sql,目前我只有树。

WITH RECURSIVE hierarchy AS (
    SELECT
        id,
        name,
        dimensionvalueid,
        0 AS level
    FROM
        dimensionvalue d
    WHERE
        dimensionvalueid IS NULL
    
UNION ALL
SELECT
    e.id,
    e.name,
    e.dimensionvalueid,
    hierarchy.level + 1
FROM
    dimensionvalue e,
    hierarchy
WHERE
    e.dimensionvalueid = hierarchy.id
)
SELECT
    d.id, d.dimensionvalueid, d.name, v.volume
FROM
    hierarchy d
    LEFT JOIN valuation v ON v.dimensionvalueid = d.id
        
    GROUP BY
        d.id,
        d.dimensionvalueid,
        d.name,
        v.volume
    ORDER BY
        d.id;

I have gotten the tree but I want to get the cumulative sum of volume from bottom up to all parent nodes.我已经得到了树,但我想获得从下到上到所有父节点的体积累积总和。 In my application only lower level volume are added which gets add up to the parent.在我的应用程序中,仅添加了较低级别的音量,这些音量加到了父级中。

Later I want to nest the flat data as follows: The output I want is:后来我想嵌套平面数据如下:我想要的output是:

   [
  {
    "id": 1,
    "name": "A1",
    "dimensionValueId": null,
    "sumVolume": 300,
    "children": [
      {
        "id": 2,
        "name": "A1:1",
        "dimensionValueId": 1,
        "sumVolume": 300,
        "children": [
          {
            "id": 3,
            "name": "A1:1:1",
            "dimensionValueId": 2,
            "sumVolume": 300,
            "children": [
              {
                "id": 4,
                "name": "A1:1:1:1",
                "dimensionValueId": 3,
                "sumVolume": 200,
                "children": null
              },
              {
                "id": 5,
                "name": "A1:1:1:2",
                "dimensionValueId": 3,
                "sumVolume": 100,
                "children": null
              }
            ]
          }
        ]
      }
    ]
  },
  {
    "id": 6,
    "name": "B1",
    "dimensionValueId": null,
    "sumVolume": 200,
    "children": [
      {
        "id": 7,
        "name": "B1:1",
        "dimensionValueId": 6,
        "sumVolume": 100,
        "children": null
      },
      {
        "id": 8,
        "name": "B1:2",
        "dimensionValueId": 6,
        "sumVolume": 100,
        "children": [
          {
            "id": 9,
            "name": "B1:2:1",
            "dimensionValueId": 6,
            "sumVolume": 100,
            "children": null
          }
        ]
      }
    ]
  }
]

Using a recursive cte :使用递归cte

with recursive cte(id, h) as (
   select d.id, ('['||d.id||']')::jsonb from dimensionvalue d where d.dimensionvalueid is null
   union all
   select d.id, c.h || ('['||c.id||']')::jsonb from cte c 
   join dimensionvalue d on d.dimensionvalueid = c.id
),
cum_sum(id, s) as (
   select d.id, sum(v1.volume) from dimensionvalue d 
   join cte c on (exists (select 1 from jsonb_array_elements(c.h) v where v.value::int = d.id) 
              and not exists (select 1 from dimensionvalue d1 where d1.dimensionvalueid = c.id)) 
   join valuation v1 on v1.dimensionvalueid = c.id group by d.id
),
tree(id, p, js) as (
   select d.id, d.dimensionvalueid, 'null'::json from dimensionvalue d where not exists (
       select 1 from dimensionvalue d1 where d1.dimensionvalueid = d.id)
   union all
   select d4.id, d4.p, json_agg(d4.js) js from (
       select d.id id, d.dimensionvalueid p, json_build_object('id', t.id, 'name', d3.name, 
            'dimensionValueId', d3.dimensionvalueid, 
            'sumVolume', coalesce(c.s, v1.volume), 'children', t.js) js 
       from dimensionvalue d join tree t on d.id = t.p 
       left join cum_sum c on c.id = t.id join valuation v1 on v1.dimensionvalueid = t.id 
       join dimensionvalue d3 on d3.id = t.id) d4 group by d4.id, d4.p
)
select jsonb_pretty(t3.js::jsonb) from (
   select json_agg(json_build_object('id', t.id, 'name', d3.name, 'dimensionValueId', d3.dimensionvalueid, 'sumVolume', c.s, 'children', t.js)) js 
   from (select t1.id, json_agg(v.value) js 
         from tree t1 cross join json_array_elements(t1.js) v 
         where t1.p is null group by t1.id) t 
   join cum_sum c on c.id = t.id join dimensionvalue d3 on d3.id = t.id) t3

See fiddle . 见小提琴

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM