Функция LAG с двумя разными перегородками - PullRequest
1 голос
/ 14 февраля 2020

У меня есть таблица с несколькими календарями внутри, и мне нужно получить предыдущий рабочий день для каждой строки в таблице.

Calendar ID     Date    Business Day    Previous Business Day
AC1         24/12/2030      Y                   -
AC1         25/12/2030      N               24/12/2030
AC1         26/12/2030      N               24/12/2030
AC1         27/12/2030      Y               24/12/2030
AC1         28/12/2030      N               27/12/2030
AC1         29/12/2030      N               27/12/2030
AC1         30/12/2030      Y               27/12/2030
AC1         31/12/2030      Y               30/12/2030
AC2         01/01/2010      Y                   -
AC2         02/01/2010      N               01/01/2010
AC2         03/01/2010      N               01/01/2010
AC2         04/01/2010      Y               01/01/2010
AC2         05/01/2010      Y               04/01/2010

Я пытался использовать функцию LAG для достижения этой цели но я не могу получить правильный возврат для каждого элемента. В итоге я разделил его на два запроса. Когда рабочий день является рабочим, я могу использовать:

CASE WHEN BUSINESS_DAY = 'Y' THEN LAG(CALENDAR_DATE,1,null) OVER(PARTITION BY CALENDAR_ID Order By CALENDAR_ID asc, CALENDAR_DATE asc) FROM CALENDAR Where BUSINESS_DAY = 'Y' 

Когда это нерабочий день, я должен был поместить его в табличную функцию и применить кросс-кросс (есть миллионы строк, и это очень медленно). Есть ли способ лучше?

1 Ответ

2 голосов
/ 14 февраля 2020

Это НЕ проблема пробелов и островков. Это всего лишь накопленная максимальная проблема:

select t.*,
       max(case when businessday = 'Y' then date end) over
           (partition by calendarid
            order by date
            rows between unbounded preceding and 1 preceding
           ) as prev_businessday
from t;

РЕДАКТИРОВАТЬ:

Эквивалентный логарифм c на следующий рабочий день:

       min(case when businessday = 'Y' then date end) over
           (partition by calendarid
            order by date
            rows between 1 following and unbounded following
           ) as next_businessday

Вы также можете переверните сортировку:

       min(case when businessday = 'Y' then date end) over
           (partition by calendarid
            order by date desc
            rows between unbounded preceding and 1 preceding
           ) as next_businessday

Лично мне эта версия немного сложнее визуализировать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...