我有一个值表,其有效期从开始日期开始,如下所示:
select x.*
into #t
from
(select 15 as value, '2012.05.20' as start-datedate
union
select 15, '2012.06.20'
union
select 15, '2012.07.20'
union
select 16, '2012.08.20'
union
select 17, '2012.09.20'
union
select 15, '2012.11.20'
union
select 17, '2012.12.20'
) x
所以表格如下:
select * from #t order by date
value start-date
-----------------------------
15 2012.05.20
15 2012.06.20
15 2012.07.20
16 2012.08.20
17 2012.09.20
15 2012.11.20
17 2012.12.20
我的问题是如何制作一个时间段表,其中每个值都有效。它应该是这样的:
value start_date end_date
15 2012.05.20 2012.08.20
16 2012.08.20 2012.09.20
17 2012.09.20 2012.11.20
15 2012.11.20 2012.12.20
17 2012.12.20
谢谢!
答案 0 :(得分:1)
不确定这是否是最佳解决方案,但认为它可以实现您所追求的目标:http://sqlfiddle.com/#!3/d41d8/21691
select value, min(startdate) start_date, nextDate end_date
from
(
select value
, startdate
, (
select min(startdate)
from #t t2
where t2.value != t1.value
and t2.startdate > t1.startdate
) nextDate
from #t t1
) y
group by value, nextDate
order by start_date
答案 1 :(得分:0)
drop table #t
select x.*
into #t
from
(select 15 as value, cast( '2012.05.20' as date ) as startdate
union
select 15, '2012.06.20'
union
select 15, '2012.07.20'
union
select 15, '2012.11.20'
union
select 17, '2012.12.20'
union
select 17, '2012.09.20'
union
select 16, '2012.08.20'
) x
;with "cte"
as
(
select
rank() over ( partition by t1."value" order by t1."startdate" ) as "rank"
, t1."value"
, t1."startdate"
, ISNULL ( t2."startdate", dateadd( month, 1, cast( t1."startdate" as date ))) as "enddate"
from #t as t1
left join #t as t2
on 1 = 1
and t1."value" = t2."value"
and datediff( month, t1."startdate", t2."startdate" ) = 1
)
, "cte2"
as
(
select
c1.value
, c1."startdate"
, c1."enddate"
from
cte c1
left join
cte c2
on 1 = 1
and c1."rank" + 1 = c2."rank"
and c1."value" = c2."value"
)
, "cte3"
as
(
select
value, startdate
from cte2
union all
select
value, enddate
from cte2
)
, "cte4"
as
(
select
*
, count( 1 ) over ( partition by value, startdate ) as "no"
from
cte3
)
, "cte5"
as
(
select
row_number() over ( partition by "value" order by "startdate" ) as "rn"
, *
from
cte4
where
"no" = 1
)
select
c1."value"
, c1."startdate"
, c2."startdate" as "endtime"
from
cte5 as c1
inner join cte5 as c2
on
1 = 1
and c1."rn" + 1 = c2."rn"
and c1."value" = c2."value"
and c1."rn" % 2 = 1
order by
"value"
, "startdate"
请参阅SQL-Fiddle