如何在 CTE 中对 SQL 服务器中从当前行到最后一行的列的值求和

How to sum the values of a column in SQL Server from the current row to the last within a CTE

SQL FIDDLE

我尝试对来自 的 CTE 中的列 qx 求和,创建一个名为 qxsum 的计算列,如下所示:

declare @idade int = 25
declare @sexo char = 'm'

;with cte as (
    select
        @idade as idade,
        @sexo as sexo,
        case when @sexo = 'm' then mor.Masculino else mor.Feminino end as qx,
        cast((sum(1.0) over (order by @idade rows between current row and unbounded following)) as float) as qxsum
     from Mortalidade as mor
     where mor.Idade = @idade

     union all

      select
          cte.idade + 1,
          cte.sexo,
          mor.qx,
          cast((sum(cte.qx) over (order by @idade rows between current row and unbounded following)) as float) as qxsum
      from cte

      outer apply (
          select
              case when cte.sexo = 'm' then mor.Masculino else mor.Feminino end as qx
          from Mortalidade as mor
          where mor.Idade = cte.Idade + 1
      ) mor

      where cte.Idade < 120
) select * from cte option (maxrecursion 0);

例如,SQL Fiddle 上面的 25 岁 qxsum 应该是 qx 从 25 岁到 120 岁的总和。

但是 SQL 服务器返回相同的值滞后一行,因为我犯了错误而且我不知道我犯了哪个错误。

您想按 idade而不是变量 @idade(其值为所有行都相同)。此外,要为大于或等于当前行的所有年龄生成 window sum(),您可以按 descending idade(因此不需要 rows 帧)。

我发现使用递归 cte 生成 idade 的列表,然后在主查询中将 table 与 left join 一起使用更简单。

declare @idade int = 25;
declare @sexo char = 'm';

with cte as (
    select @idade idade
    union all select idade + 1 from cte where idade < 120
)
select
    c.idade,
    @sexo sexo,
    case when @sexo = 'm' then m.masculino else m.feminino end as qx,
    sum(case when @sexo = 'm' then m.masculino else m.feminino end) 
        over(order by c.idade desc) qxsum
from cte c
left join mortalidade m on m.idade = c.idade
order by c.idade
option (maxrecursion 0);

请注意,您应该将性别存储在不同的行而不是列中(这样可以避免需要条件逻辑)。

对于您的示例数据,this query yields:

idade | sexo | qx           | qxsum        
----: | :--- | :----------- | :------------
   25 | m    | 0.0019300000 | 28.0897400000
   26 | m    | 0.0019600000 | 28.0878100000
   27 | m    | 0.0019900000 | 28.0858500000
   28 | m    | 0.0020300000 | 28.0838600000
   29 | m    | 0.0020800000 | 28.0818300000
   30 | m    | 0.0021300000 | 28.0797500000
  ............. more rows here ............
  111 | m    | 1.0000000000 | 10.0000000000
  112 | m    | 1.0000000000 | 9.0000000000 
  113 | m    | 1.0000000000 | 8.0000000000 
  114 | m    | 1.0000000000 | 7.0000000000 
  115 | m    | 1.0000000000 | 6.0000000000 
  116 | m    | 1.0000000000 | 5.0000000000 
  117 | m    | 1.0000000000 | 4.0000000000 
  118 | m    | 1.0000000000 | 3.0000000000 
  119 | m    | 1.0000000000 | 2.0000000000 
  120 | m    | 1.0000000000 | 1.0000000000