【问题标题】:Concatenate date ranges in SQL (T/SQL preferred)在 SQL 中连接日期范围(首选 T/SQL)
【发布时间】:2011-09-09 05:06:41
【问题描述】:

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

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

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

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

【问题讨论】:

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


    【解决方案1】:
    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
    

    【讨论】:

    • 不幸的是,我陷入了使用 SQL 2000 的黑暗时代,但我会在获得测试/开发服务器设置后立即尝试...
    • @ggonsalv - 对于 SQL Server 2000,我可能会使用游标。还有另一种使用子查询的方法见这里manning.com/nielsen/SampleChapter5.pdf,但性能真的很差。
    • @ggonsalv - 在等待服务器进行测试时,在此处进行测试。 data.stackexchange.com/stackoverflow/q/112154
    【解决方案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
    

    【讨论】:

      【解决方案3】:

      对月份使用 DatePart 函数将为您提供所需的“组”

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多