Как суммировать значения столбца в SQL Server от текущей строки до последней в CTE - PullRequest
0 голосов
/ 12 апреля 2020

SQL FIDDLE

Я попытался суммировать столбец qx в моем CTE от текущей строки до последней строки , создав вычисляемый столбец с именем 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);

Например, для возраста 25 в SQL Fiddle выше qxsum должна быть сумма от qx от 25 до 120 лет .

Но SQL Сервер возвращает то же значение, отставая на одну строку, потому что я делаю ошибки, и я не знаю, какую ошибку я делаю.

1 Ответ

1 голос
/ 12 апреля 2020

Вы хотите заказать по столбцу idade, а не по переменной @idade (значение которой одинаково для всех строк). Кроме того, чтобы создать окно sum() для всех возрастов, которые больше или равны возрасту текущей строки, вы можете просто упорядочить записи по по убыванию idade (поэтому нет необходимости в rows frame).

Я считаю, что проще использовать рекурсивный cte, чтобы просто сгенерировать список idade s, а затем перенести таблицу с 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);

Обратите внимание, что вы должны хранить гендеры в разных строках, а не в столбцах (это избавит вас от необходимости условной логики c).

Для ваших примеров данных этот запрос дает :

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 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...