从双树结构SQL Server求和值的递归视图

首先抱歉我的问题有很多重新发布,我是新来的,习惯了正确而明确地提问 .

我正在处理一个递归视图,它总结了双树结构中的值 .

我已经研究过并发现了许多关于递归总和的问题,但他们的解决方案似乎都没有特别适用于我的问题 .

到目前为止,我在聚合右侧单元格中的值时遇到了问题,逻辑是我需要每年每个元素在其父级中的总和以及给定元素的所有年份的总和 .

这是我的表和实际脚本的小提琴:

SQL Fiddle

这是我正在寻找的输出的屏幕截图:

enter image description here

My question is: 如何在这个双树结构中获取我的视图以聚合从子到父的值?

回答(1)

3 years ago

如果我正确理解了您的问题,那么您正尝试在两个不同的级别上进行聚合以显示在单个结果集中 .

Clarification Scenario:

以下是我认为您试图实现的过度简化的示例数据集 .

create table #agg_table
    (
        group_one int
        , group_two int
        , group_val int
    )

insert into #agg_table
values (1, 1, 6)
    , (1, 1, 7)
    , (1, 2, 8)
    , (1, 2, 9)
    , (2, 3, 10)
    , (2, 3, 11)
    , (2, 4, 12)
    , (2, 4, 13)

根据上面的示例数据,您希望看到以下输出:

+-----------+-----------+-----------+
| group_one | group_two | group_val |
+-----------+-----------+-----------+
|         1 | NULL      |        30 |
|         1 | 1         |        13 |
|         1 | 2         |        17 |
|         2 | NULL      |        46 |
|         2 | 3         |        21 |
|         2 | 4         |        25 |
+-----------+-----------+-----------+

可以通过使用SQL Server中的group by grouping sets(链接中的示例G.)语法来实现此输出,如下面的查询所示:

select a.group_one
, a.group_two
, sum(a.group_val) as group_val
from #agg_table as a
group by grouping sets
    (
        (
            a.group_one
            , a.group_two
        )
        ,
        (
            a.group_one
        )
    )
order by a.group_one
, a.group_two

这对您的场景意味着什么,我相信您的递归-CTE不是问题 . 唯一需要改变的是来自整个CTE的最终选择查询 .

Answer:

with Temp (EntityOneId, EntityOneParentId, EntityTwoId, EntityTwoParentId, Year, Value)
as
(
    SELECT E1.Id, E1.ParentId, E2.Id, E2.ParentId, VY.Year, VY.Value 
    FROM ValueYear AS VY
    FULL OUTER JOIN EntityOne AS E1
    ON VY.EntityOneId = E1.Id
    FULL OUTER JOIN EntityTwo AS E2
    ON VY.EntityTwoId = E2.Id
),
T (EntityOneId, EntityOneParentId, EntityTwoId, EntityTwoParentId, Year, Value, Levels)
as
(
    Select 
        T1.EntityOneId,
        T1.EntityOneParentId,
        T1.EntityTwoId,
        T1.EntityTwoParentId,
        T1.Year,
        T1.Value,
        0 as Levels
    From
        Temp
            As T1
    Where
        T1.EntityOneParentId is null
    union all
    Select
        T1.EntityOneId,
        T1.EntityOneParentId,
        T1.EntityTwoId,
        T1.EntityTwoParentId,
        T1.Year,
        T1.Value,
        T.Levels +1
    From
        Temp 
            AS T1
    join
        T
            On T.EntityOneId = T1.EntityOneParentId
)
Select 
    T.EntityOneId,
    T.EntityOneParentId,
    T.EntityTwoId,
    T.EntityTwoParentId,
    T.Year,
    sum(T.Value) as Value
from T
group by grouping sets
  (
    (
      T.EntityOneId,
      T.EntityOneParentId,
      T.EntityTwoId,
      T.EntityTwoParentId,
      T.Year
    )
    ,
    (
      T.EntityOneId,
      T.EntityOneParentId,
      T.EntityTwoId,
      T.EntityTwoParentId
    )
  )
order by T.EntityOneID
, T.EntityOneParentID
, T.EntityTwoID
, T.EntityTwoParentID
, T.Year

仅供参考 - 我认为样本数据没有完全匹配预期输出所需的记录,但SQL Fiddle中的最后20个记录与预期输出完全匹配 .