| andMegaM |
|---|
2 Ivan Durak
А можно вариант без курсора? |
Решение в лоб с всеобщим объединением диапазонов и заполнением дырок:
declare @t1 table ([START] date, [END] date)
insert into @t1 ([START], [END]) values
('20110110','20110120'),
('20110115','20110125'),
('20110117','20110220'),
('20110301','20110315')
declare @t2 table ([START] date, [END] date)
insert into @t2 ([START], [END]) values
('20110101','20110130'),
('20110310','20110320')
;with tb1( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START] ) as RN, [START], [END]
FROM @t1
)
,ts1( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START]), t.[START], t.[END]
FROM (
SELECT MIN(t1.[START]) as [START], ISNULL(t2.[END], t1.[END]) as [END]
FROM tb1 as t1
OUTER APPLY(
SELECT MAX( t2.[END] ) as [END]
FROM tb1 as t2
WHERE t1.RN < t2.RN
and
/*
not ((t1.[END] < t2.[START]) or (t2.[END] < t1.[START]))
and
not ((t1.[END] < t2.[START]) or (t2.[END] < t1.[START]))
*/
-- После смены базиса 'OR' на 'AND'
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
and
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
) as t2
GROUP BY ISNULL(t2.[END], t1.[END])
) as t
)
,tb2( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START] ) as RN, [START], [END]
FROM @t2
)
,ts2( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START]), t.[START], t.[END]
FROM (
SELECT MIN(t1.[START]) as [START], ISNULL(t2.[END], t1.[END]) as [END]
FROM tb2 as t1
OUTER APPLY(
SELECT MAX( t2.[END] ) as [END]
FROM tb2 as t2
WHERE t1.RN < t2.RN
and
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
and
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
) as t2
GROUP BY ISNULL(t2.[END], t1.[END])
) as t
)
,ts( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START]), t.[START], t.[END]
FROM (
SELECT [START], [END]
FROM ts1
UNION ALL
SELECT [START], [END]
FROM ts2
) as t
)
,tss( RN, [START], [END] ) as (
SELECT ROW_NUMBER() OVER(ORDER BY [START]), t.[START], t.[END]
FROM (
SELECT MIN(t1.[START]) as [START], ISNULL(t2.[END], t1.[END]) as [END]
FROM ts as t1
OUTER APPLY(
SELECT MAX( t2.[END] ) as [END]
FROM ts as t2
WHERE t1.RN < t2.RN
and
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
and
((t2.[START] <= t1.[END]) AND (t1.[START] <= t2.[END]))
) as t2
GROUP BY ISNULL(t2.[END], t1.[END])
) as t
)
select [START], [END], 1 as [isPresent]
from tss
union all
select t1.[END], t2.[START], 0 as [isPresent]
from tss as t1
inner join tss as t2 on
t1.RN = t2.RN-1
order by [START]Может это и не то, что Вы хотели, но мне было интересно решить задачу в такой постановке.