Используя таблицу событий, мне нужно вернуть дату и тип для:
- первое событие
- самое последнее (ненулевое) событие
Самое последнее событие может иметь нулевые значения, которые в этом случае должны возвращать самое последнее ненулевое значение
Я нашел несколько статей, а также посты здесь на SO, которые похожи (возможно, даже идентичны), но не в состоянии расшифровать или понять решение - то есть
Заполнить нулевые значения последней ненулевой суммой - Oracle SQL
https://www.itprotoday.com/sql-server/last-non-null-puzzle
https://koukia.ca/common-sql-problems-filling-null-values-with-preceding-non-null-values-ad538c9e62a6
Таблица выглядит следующим образом - есть дополнительные столбцы, но я включаю только 3 для простоты. Также обратите внимание, что first Type and Date могут быть нулевыми. В этом случае возврат нуля является желательным.
╔═══════╦════════╦════════════╗
║ Email ║ Type ║ Date ║
╠═══════╬════════╬════════════╣
║ A ║ Create ║ 2019-04-01 ║
║ A ║ Update ║ 2019-04-02 ║
║ A ║ null ║ null ║
╚═══════╩════════╩════════════╝
Вывод должен быть:
╔═══════╦═══════════╦════════════╦══════════╦════════════╗
║ Email ║ FirstType ║ FirstDate ║ LastType ║ LastDate ║
╠═══════╬═══════════╬════════════╬══════════╬════════════╣
║ A ║ Create ║ 2019-04-01 ║ Update ║ 2019-04-02 ║
╚═══════╩═══════════╩════════════╩══════════╩════════════╝
Первый метод, который я попробовал, состоял в том, чтобы присоединить таблицу к себе, используя подзапрос, который находит даты MIN и MAX, используя операторы case:
select
Email,
max(case when T1.Date = T2.Min_Date then T1.Type end) as FirstType,
max(case when T1.Date = T2.Min_Date then T1.Date end) as FirstDate,
max(case when T1.Date = T2.Max_Date then T1.Type end) as LastType,
max(case when T1.Date = T2.Max_Date then T1.Date end) as LastDate,
from
T1
join
(select
EmailAddress,
max(Date) as Max_Date,
min(Date) as Min_Date
from
Table1
group by
Email
) T2
on
T1.Email = T2.Email
group by
T1.Email
Казалось бы, это работает для значений MIN, но значения MAX будут возвращать ноль.
Чтобы решить проблему возврата последнего не-значения, я попытался это сделать:
select
EmailAddress,
max(Date) over (partition by EmailAddress rows unbounded preceding) as LastDate,
max(Type) over (partition by EmailAddress rows unbounded preceding) as LastType
from
T1
group by
EmailAddress,
Date,
Type
Однако, это дает 3 строки вместо 1.
Я признаю, что не совсем понимаю аналитические функции, поскольку мне не приходилось долго с ними сталкиваться. Любая помощь будет принята с благодарностью.
Edit:
Вышеупомянутый пример является точным представлением того, как могут выглядеть данные, однако приведенный ниже пример является точным примером данных, которые я использую.
Пример:
╔═══════╦════════╦════════════╗
║ Email ║ Type ║ Date ║
╠═══════╬════════╬════════════╣
║ A ║ Create ║ 2019-04-01 ║
║ A ║ null ║ null ║
╚═══════╩════════╩════════════╝
Желаемый результат:
╔═══════╦═══════════╦════════════╦══════════╦════════════╗
║ Email ║ FirstType ║ FirstDate ║ LastType ║ LastDate ║
╠═══════╬═══════════╬════════════╬══════════╬════════════╣
║ A ║ Create ║ 2019-04-01 ║ Create ║ 2019-04-01 ║
╚═══════╩═══════════╩════════════╩══════════╩════════════╝
Дополнительный вариант использования:
╔═══════╦════════╦════════════╗
║ Email ║ Type ║ Date ║
╠═══════╬════════╬════════════╣
║ A ║ null ║ null ║
║ A ║ Create ║ 2019-04-01 ║
╚═══════╩════════╩════════════╝
Желаемый результат:
╔═══════╦═══════════╦════════════╦══════════╦════════════╗
║ Email ║ FirstType ║ FirstDate ║ LastType ║ LastDate ║
╠═══════╬═══════════╬════════════╬══════════╬════════════╣
║ A ║ null ║ null ║ Create ║ 2019-04-01 ║
╚═══════╩═══════════╩════════════╩══════════╩════════════╝