У меня есть следующая таблица:
Таблица А:
Я хочу, чтобы вывод выглядел так:
Вычислите разницу в днях между transaction_date(где cancel_flag = No) и transaction_date(где cancel_flag = Yes).
Если имеется более 1 cancel_flag = Yes. Используемая разница в днях должна быть минимальной.
Заранее спасибо,
Для каждой записи единственные строки «отмены», которые вас интересуют, — это непосредственно перед или сразу после текущей строки, когда набор данных отсортирован по транзакции_дате. Из-за этого решения с использованием оконных функций кажутся здесь вполне уместными.
Для любой заданной строки вы можете получить дату предыдущей транзакции отмены с помощью
max(Case When Cancel_Flag='Yes' Then transaction_date End)
Over (Partition By ID Order By Transaction_Date Rows Between Unbounded Preceding And Current Row)
, и дата следующей транзакции отмены с
min(Case When Cancel_Flag='Yes' Then transaction_date End)
Over (Partition By ID Order By Transaction_Date Rows Between Current Row And Unbounded Following)
Просто используйте каждый в datediff() с текущей датой транзакции строк, и у вас есть два возможных результата, которые вы можете выбрать, чтобы получить окончательный результат.
Select ID,Transaction_Date,Cancel_Flag,
Case When prior_cancel is null or next_cancel<abs(prior_cancel)
Then next_cancel Else prior_cancel End as Days_Since_Cancel
From (
Select A.*,
datediff(day,Transaction_Date,
max(Case When Cancel_Flag='Yes' Then transaction_date End)
Over (Partition By ID Order By Transaction_Date Rows Between Unbounded Preceding And Current Row)
) as prior_cancel,
datediff(day,Transaction_Date,
min(Case When Cancel_Flag='Yes' Then transaction_date End)
Over (Partition By ID Order By Transaction_Date Rows Between Current Row And Unbounded Following)
) as next_cancel
From Table_A A
)
Order By ID,Transaction_Date
РЕДАКТИРОВАТЬ ДОПОЛНЕНИЕ Обратите внимание, что вместо min(...) вы можете использовать first_value(... Игнорировать нули), а вместо max(...) вы можете использовать last_value(... Игнорировать нули). Это может быть немного более эффективным, потому что, хотя вы не можете определить минимум и максимум, не исследуя всю рамку окна, теоретически первое и последнее можно определить, не исследуя каждый элемент. Они всегда функционально эквивалентны, если столбец Order By и min/max(столбец) совпадают, в данном случае Transaction_Date.
Если вы посмотрите на любую данную запись, ее ближайшая по времени запись об отмене — это либо отмененная непосредственно перед ней по времени, либо та, что сразу после нее по времени. Таким образом, упорядочив список по Transaction_Date, максимальная дата отмененных записей до нее и минимальная дата после нее ближе, чем любая другая запись с cancel_flag='yes'. Так что неважно, сколько раз запись отменили, этот найдет самый близкий.
Спасибо за это Крис! Что делать, если у меня больше 2 cancel_flag = Yes?