У меня есть хитрая проблема с пропусками и островами. Острова дат должны быть идентифицированы в иерархии полей.
Эта проблема пробелов и островков отличается от традиционного типа в нескольких отношениях:
- Даты представлены в формате диапазона в двух полях (StartDate и EndDate)
- Группировка островов должна учитывать иерархию полей
- Эти данные содержатся в Cloudera 6.2x, который ограничивает некоторые потенциальные решения (например, рекурсивный cte)
Если конечная дата иерархии находится в тот же день или день до начальной даты следующего вхождения, это должен быть остров. Как я могу сделать это, учитывая мои ограничения и пример данных?
Я попытался найти несколько решений, включая следующий псевдокод:
создать row_number над разделом полей иерархии, упорядоченным по этим иерархиям и StartDate.
определить пробелы с помощью логики регистра
когда days_add (end_date, 1)> = lead (start_date, 1)
и row_number
идентифицировать острова с помощью логики регистра:
когда row_number = 1, то 1
когда лаг (пробелы, 1) = 1, то лаг (острова, 1) + 1
остальное отставание (острова, 1)
Это должно логически работать для создания островков, которые я могу использовать для группировки и получения минимума startDate и максимума EndDate, сгруппированных по иерархии. Когда я ставлю данные в Excel и применяю этот алгоритм, я получаю правильные результаты. По-видимому, в Cloudera нет оценки лагов (островов, 1) при оценке каждой записи?
CREATE TABLE sampleInput (
person int,
level1 int,
level2 int,
level3 int,
StartDate DATETIME,
EndDate DATETIME,
rowNumber int)
INSERT INTO sampleInput
VALUES
(1,1,17,101,'2001-09-16','2001-09-19',1),
(1,1,17,102,'2001-09-20','2001-09-24',2),
(1,1,17,103,'2001-04-15','2001-04-25',3),
(1,1,17,104,'2001-08-02','2001-08-15',4),
(1,1,20,105,'2001-03-10','2001-03-18',5),
(1,1,20,105,'2001-04-01','2001-04-08',6),
(1,1,20,105,'2001-07-20','2001-07-25',7),
(1,1,20,106,'2001-02-20','2001-02-08',8),
(1,1,31,107,'2001-04-25','2001-04-30',9),
(1,1,31,107,'2001-05-01','2001-05-29',10),
(2,3,42,111,'2002-04-05','2002-04-05',11),
(2,3,42,111,'2002-04-06','2002-04-06',12),
(2,3,42,111,'2002-04-07','2002-04-30',13),
(2,3,42,111,'2002-05-01','2002-05-25',14),
(2,3,42,111,'2002-05-28','2002-06-01',15),
(2,3,42,111,'2002-06-04','2002-06-06',16),
(2,3,42,111,'2002-06-08','2002-06-20',17)
И
CREATE TABLE sampleOutput (
person int, level1 int, level2 int, level3 int,
StartDate DATETIME, EndDate DATETIME ,rowNumberConcat varchar(max)
)
INSERT INTO sampleOutput
VALUES
(1,1,17,101,'2001-09-16','2001-09-19','1'),
(1,1,17,102,'2001-09-20','2001-09-24','2'),
(1,1,17,103,'2001-04-15','2001-04-25','3'),
(1,1,17,104,'2001-08-02','2001-08-15','4'),
(1,1,20,105,'2001-03-10','2001-03-18','5'),
(1,1,20,105,'2001-04-01','2001-04-08','6'),
(1,1,20,105,'2001-07-20','2001-07-25','7'),
(1,1,20,106,'2001-02-20','2001-02-08','/'),
(1,1,31,107,'2001-04-25','2001-05-29','9,10'),
(2,3,42,111,'2002-04-05','2002-05-25','11,12,13,14'),
(2,3,42,111,'2002-05-28','2002-06-01','15'),
(2,3,42,111,'2002-06-04','2002-06-06','16'),
(2,3,42,111,'2002-06-08','2002-06-20','17')
Я включил ввод и вывод в следующую скрипту SQL:
http://www.sqlfiddle.com/#!18/770768/1
Включенные поля rowNumber и rowNumberConcat включены только для отображения происхождения входных и выходных данных.
Скрипка настроена для MSSQL только потому, что нет опции Cloudera. В качестве примечания: если бы я использовал другой аромат или совершенно другой сайт, пожалуйста, дайте мне знать.