SQL中的连接日期范围(首选T / SQL)

时间:2011-09-09 05:06:41

标签: sql-server tsql sql-server-2000 gaps-and-islands

我需要将日期和代码的行连接到日期范围

包含两列复合主键(日期和代码)的表

Date        Code  
1/1/2011    A  
1/2/2011    A  
1/3/2011    A  
1/1/2011    B  
1/2/2011    B
2/1/2011    A
2/2/2011    A
2/27/2011   A
2/28/2011   A
3/1/2011    A
3/2/2011    A
3/3/2011    A
3/4/2011    A

需要转换为

Start Date    End Date    Code
1/1/2011      1/3/2011    A
2/1/2011      2/2/2011    A
1/1/2011      1/2/2011    B
2/27/2011     3/4/2011    A

还有其他方法或光标循环是唯一的方法吗?

3 个答案:

答案 0 :(得分:3)

declare @T table
(
  [Date] date,
  Code char(1)
)

insert into @T values
('1/1/2011','A'),  
('1/2/2011','A'),  
('1/3/2011','A'),  
('1/1/2011','B'),  
('1/2/2011','B'), 
('3/1/2011','A'),
('3/2/2011','A'),
('3/3/2011','A'),
('3/4/2011','A')

;with C as
(
  select *,
         datediff(day, 0, [Date]) - row_number() over(partition by Code 
                                                      order by [Date]) as rn
  from @T
)  
select min([Date]) as StartDate,
       max([Date]) as EndDate,
       Code
from C
group by Code, rn

答案 1 :(得分:2)

sql server 2000有它的局限性。重写了解决方案,使其更具可读性。

declare @t table 
( 
  [Date] datetime, 
  Code char(1) 
) 

insert into @T values 
('1/1/2011','A'),   
('1/2/2011','A'),   
('1/3/2011','A'),   
('1/1/2011','B'),   
('1/2/2011','B'),  
('3/1/2011','A'), 
('3/2/2011','A'), 
('3/3/2011','A'), 
('3/4/2011','A') 

select a.code, a.date, min(b.date)
from
(
    select *
    from @t t 
    where not exists (select 1 from @t where t.code = code and t.date -1 = date)
) a
join 
(
    select *
    from @t t 
    where not exists (select 1 from @t where t.code = code and t.date  = date -1)
) b
on a.code = b.code and a.date <= b.date
group by a.code, a.date

答案 2 :(得分:1)

使用月份的DatePart功能可以获得您想要的“组”

SELECT Min(Date) as StartDate, Max(Date) as EndDate, Code 
FROM ThisTable Group By DatePart(m, Date), Code