根据单行的日期范围分为多行

时间:2017-03-29 17:20:28

标签: tsql sql-server-2008-r2

我有一张表可以捕捉约会,有些是单日约会,有些是多日约会,所以数据看起来像

AppointmentId   StartDate   EndDate
9               2017-04-12  2017-04-12
10              2017-05-01  2017-05-03
11              2017-06-01  2017-06-01

我想将多天约会拆分为单日,所以我想要实现的结果就像

AppointmentId   StartDate   EndDate
9               2017-04-12  2017-04-12
10              2017-05-01  2017-05-01
10              2017-05-02  2017-05-02
10              2017-05-03  2017-05-03
11              2017-06-01  2017-06-01

所以我将约会ID 10拆分成多行。我检查了一些其他问题 here但这些只是基于单个开始日期和结束日期进行拆分而不是基于表格数据

2 个答案:

答案 0 :(得分:2)

您可以使用日历或日期表进行此类操作。

对于内存中只有152kb,您可以在表格中拥有30年的日期:

/* dates table */
declare @fromdate date = '20000101';
declare @years    int  = 30;
/* 30 years, 19 used data pages ~152kb in memory, ~264kb on disk */
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
select top (datediff(day, @fromdate,dateadd(year,@years,@fromdate)))
    [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
into dbo.Dates
from n as deka cross join n as hecto cross join n as kilo
               cross join n as tenK cross join n as hundredK
order by [Date];
create unique clustered index ix_dbo_Dates_date
  on dbo.Dates([Date]);

如果不采取创建表格的实际步骤,您可以在common table expression内使用它:

declare @fromdate date = '20161229'; 
declare @thrudate date = '20170103';
;with n as (select n from (values(0),(1),(2),(3),(4),(5),(6),(7),(8),(9)) t(n))
, dates as (
  select top (datediff(day, @fromdate, @thrudate)+1) 
      [Date]=convert(date,dateadd(day,row_number() over(order by (select 1))-1,@fromdate))
  from n as deka cross join n as hecto cross join n as kilo
                cross join n as tenK cross join n as hundredK
   order by [Date]
)
select [Date]
from dates;

使用如下:

select 
    t.AppointmentId
  , StartDate = d.date
  , EndDate = d.date
from dates d
  inner join appointments t
    on d.date >= t.StartDate
   and d.date <= t.EndDate

rextester演示:http://rextester.com/TNWQ64342

返回:

+---------------+------------+------------+
| AppointmentId | StartDate  |  EndDate   |
+---------------+------------+------------+
|             9 | 2017-04-12 | 2017-04-12 |
|            10 | 2017-05-01 | 2017-05-01 |
|            10 | 2017-05-02 | 2017-05-02 |
|            10 | 2017-05-03 | 2017-05-03 |
|            11 | 2017-06-01 | 2017-06-01 |
+---------------+------------+------------+

数字和日历表参考:

答案 1 :(得分:1)

显然,日历/ Tally表将是SqlZim图示的方式(+1),但是您可以使用带有CROSS APPLY的ad-hoc计数表。

示例

Select A.AppointmentId   
      ,StartDate = B.D  
      ,EndDate   = B.D
 From  YourTable A
 Cross Apply (
                Select Top (DateDiff(DD,A.StartDate,A.EndDate)+1) D=DateAdd(DD,-1+Row_Number() Over (Order By Number),A.StartDate) 
                 From  master..spt_values
             ) B

<强>返回

AppointmentId   StartDate   EndDate
9               2017-04-12  2017-04-12
10              2017-05-01  2017-05-01
10              2017-05-02  2017-05-02
10              2017-05-03  2017-05-03
11              2017-06-01  2017-06-01