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

时间:2018-01-08 17:19:11

标签: sql sql-server tsql recursion

首先很抱歉我的问题已经多次重新发布,我已经习惯了,并且已经习惯了正确而明确地提问。

我正在处理递归视图,该视图总结了双树结构中的值。

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

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

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

SQL Fiddle

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

enter image description here

我的问题是: 如何让我的视图在这个双树结构中聚合从子到父的值?

1 个答案:

答案 0 :(得分:0)

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

澄清场景:

以下是我认为您想要实现的过度简化的样本数据集。

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 |
+-----------+-----------+-----------+

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

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的最终选择查询。

<强>答案:

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条记录与预期输出完全匹配。