2016-11-25 3 views
0

У меня есть этот набор данных, где у меня есть временной ряд в формате YYYYMM. У меня есть два столбца, которые в основном являются флагами true/false. Я хотел бы добавить две дополнительные колонки на основе этих истинных/ложных флагов, доставленных текущий диапазон:T-SQL: диапазоны заполнения Timeseries

 Default Cure 
201301 0  NULL 
201302 0  NULL 
201303 0  NULL 
201304 1  NULL 
201305 1  NULL 
201306 1  NULL 
201307 1  NULL 
201308 NULL  0 
201309 NULL  0 
201310 NULL  1 
201311 0  NULL 
201312 0  NULL 
201401 0  NULL 
201402 0  NULL 
201403 1  NULL 
201404 1  NULL 
201405 0  NULL 
201406 0  NULL 
201407 NULL  1 
201408 NULL  0 
201409 NULL  0 
201410 NULL  0 
201411 NULL  0 
201412 NULL  0 

Я этот набор данных можно увидеть в столбце по умолчанию быть установлен в 1 для периодов 201304, 05, 06, 07 и столбец Cure устанавливается равным 1 в период 201310.

в основном это означает, что таймсерий по умолчанию действует с периода 201304 до периода 201310. в конечном счете, я хотел бы, чтобы генерировать следующий набор:

 Default Cure DefaultPeriod CurePeriod 
201301 0  NULL NULL   NULL 
201302 0  NULL NULL   NULL 
201303 0  NULL NULL   NULL 
201304 1  NULL 201304   201310 
201305 1  NULL 201304   201310 
201306 1  NULL 201304   201310 
201307 1  NULL 201304   201310 
201308 NULL  0  201304   201310 
201309 NULL  0  201304   201310 
201310 NULL  1  201304   201310 
201311 0  NULL NULL   NULL 
201312 0  NULL NULL   NULL 
201401 0  NULL NULL   NULL 
201402 0  NULL NULL   NULL 
201403 1  NULL 201403   201407 
201404 1  NULL 201403   201407 
201405 0  NULL 201403   201407 
201406 0  NULL 201403   201407 
201407 NULL  1  201403   201407 
201408 NULL  0  NULL   NULL 
201409 NULL  0  NULL   NULL 
201410 NULL  0  NULL   NULL 
201411 NULL  0  NULL   NULL 
201412 NULL  0  NULL   NULL 

Возможны множественные диапазоны, но они не могут перекрытия. Как я буду добиваться этого. Я попытался сделать все виды соединения min/max в той же таблице, но я не могу найти рабочего решения.

+0

Вы говорите, что у вас есть «... два столбца, которые в основном соответствуют true/false flags ...», но есть значения «NULL». Вы используете 'NULL == 0 == FALSE'? Если да, почему бы просто не заполнить поля 'NULL'' 0? – Tony

+0

В '201308' значение' 0' для 'Cure' поддерживает диапазон, но на' 201311' значение '0' для' Default' делает * not * сохраняет диапазон. Почему нет? В '201405' значение' 0' для 'Default' * делает * сохраняет диапазон, в конце концов ... – AakashM

+0

В принципе, это не совсем ясно из вашего описания или примера a), что считается истинным, и что считается false b) то, что reules вокруг того, что составляет диапазон – AakashM

ответ

1

Это был настоящий мыслитель :)

В основном я разделив данные на «лечение» даты (c1), нумерация каждой группы (c2), а затем ищет минут и в пределах каждой исчерпан группы (c3 C4), затем применяя некоторую логику для фильтрации строк, которые идут до мин.

declare @t table 
(
    [Month] varchar(6), 
    [Default] bit, 
    [Cure] bit 
); 

insert into @t values('201301', 0,  NULL); 
insert into @t values('201302', 0,  NULL); 
insert into @t values('201303', 0,  NULL); 
insert into @t values('201304', 1,  NULL); 
insert into @t values('201305', 1,  NULL); 
insert into @t values('201306', 1,  NULL); 
insert into @t values('201307', 1,  NULL); 
insert into @t values('201308', NULL,  0); 
insert into @t values('201309', NULL,  0); 
insert into @t values('201310', NULL,  1); 
insert into @t values('201311', 0,  NULL); 
insert into @t values('201312', 0,  NULL); 
insert into @t values('201401', 0,  NULL); 
insert into @t values('201402', 0,  NULL); 
insert into @t values('201403', 1,  NULL); 
insert into @t values('201404', 1,  NULL); 
insert into @t values('201405', 0,  NULL); 
insert into @t values('201406', 0,  NULL); 
insert into @t values('201407', NULL,  1); 
insert into @t values('201408', NULL,  0); 
insert into @t values('201409', NULL,  0); 
insert into @t values('201410', NULL,  0); 
insert into @t values('201411', NULL,  0); 
insert into @t values('201412', NULL,  0); 


with c1 as 
(
    select min([Month]) [Month], 1 x from @t 
    union all 
    select [Month],1 from @t 
    where Cure = 1 
), 
c2 as 
(
    select t.[Month],[Default],[Cure], 
     sum(x) over (order by t.[Month] rows between unbounded preceding and 1 preceding) grp 
    from @t t 
    left outer join c1 on c1.[Month] = t.[Month] 
), 
c3 as 
(
    select grp, min([Month]) [Month] 
    from c2 
    where [Default] = 1 
    group by grp 
), 
c4 as 
(
    select grp, max([Month]) [Month] 
    from c2 
    where [Cure] = 1 
    group by grp 
) 
select c2.[Month], c2.[Default], c2.[Cure], 
    case when c2.[Month] >= c3.[Month] then c3.[Month] else null end as DefaultPeriod, 
    case when c2.[Month] >= c3.[Month] then c4.[Month] else null end as CurePeriod 
from c2 
left outer join c3 on c2.grp = c3.grp 
left outer join c4 on c2.grp = c4.grp 
Смежные вопросы