Накопление дат в SQL - PullRequest
       21

Накопление дат в SQL

0 голосов
/ 12 февраля 2019

У меня есть эта таблица с данными этого образца:

DECLARE @Sample TABLE (fill_date DATETIME, days_supplied INT)

INSERT INTO @Sample (fill_date, days_supplied)
VALUES (    
    '02/17/2005', --> DATEADD(dd, 500, '02/17/2005') = '07/02/2006'
    500
    ),
    (   
    '06/13/2005', --> DATEADD(dd, 30, '07/02/2006') = '08/01/2006'
    30
    ),
    (   
    '08/11/2005', --> DATEADD(dd, 30, '08/01/2006') = '08/31/2006'
    30
    )

Мне нужно добавить days_supplied to fill_date в первой строке, что будет 2006-07-02,Если в следующей строке результат будет больше, чем fill_date, мне нужно будет добавить days_supplies следующей строки к сумме days_supplied и fill_date предыдущей строки.Если результат первой строки не выше, чем fill_date следующей строки, тогда мне нужно добавить days_supplied и fill_date следующей строки и т. Д.

Это результат, который мне нужен в конце:

last_fill_date: '08/31/2006'.

Каков наилучший способ добиться этого?Любая помощь приветствуется

Ответы [ 2 ]

0 голосов
/ 12 февраля 2019

Использование оконных функций

Пример

Select *
      ,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
 From  @Sample

Возвращает

fill_date               days_supplied   NewValue
2005-02-17 00:00:00.000 500             2006-07-02 00:00:00.000
2005-06-13 00:00:00.000 30              2006-08-01 00:00:00.000
2005-08-11 00:00:00.000 30              2006-08-31 00:00:00.000

РЕДАКТИРОВАТЬ - Если вы хотите только окончательную запись

Select Top 1 
       *
      ,NewValue = DateAdd(DAY,sum(days_supplied) over (Order By Fill_date),min(fill_date) over())
 From  @Sample
 Order By NewValue desc
0 голосов
/ 12 февраля 2019

Для этого типа логики вам необходимо использовать рекурсивный CTE - увы:

with s as (
      select s.*, row_number() over (order by fill_date) as seqnum
      from sample s
     ),
     cte as (
      select fill_date, days_supplied, dateadd(day, days_supplied, fill_date) as end_date, seqnum
      from s
      where seqnum = 1
      union all
      select (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end),
             s.days_supplied,
             dateadd(day, s.days_supplied, (case when s.fill_date > cte.end_date then s.fill_date else cte.end_date end)),
             s.seqnum
      from cte join
           s
           on s.seqnum = cte.seqnum + 1
     )
select max(end_date)
from cte;

Здесь - это дБ <> скрипка.

Примечаниечто есть небольшая двусмысленность в вопросе.Я думаю, что строки упорядочены по fill_date, что и предполагает этот ответ.

...