簡體   English   中英

如何使用開始日期和結束日期從一天擴展的SQL表中輸出行?

[英]How to output the rows from a SQL table as expanded on a day basis using a start date and end date?

我正在使用SQL Server 2012 ,我有一個名為StayInfo的表。

它具有以下結構(提取):

Name    ArrDate        DepDate       ID
A       2016-03-29     2016-04-02    100
B       2016-05-10     2016-05-12    250

我想從T-SQL查詢輸出以下內容:

Name    Date          ID
A       2016-03-29   100
A       2016-03-30   100 
A       2016-03-31   100
A       2016-04-01   100
A       2016-04-03   100
B       2016-05-10   250
B       2016-05-11   250
B       2016-05-12   250

我面臨的主要困難是每天執行拆分所需的SQL代碼。

您可以使用遞歸CTE或數字表:

with cte as (
      select Name, ArrDate, DepDate, ID
      from t
      union all
      select Name, dateadd(day, 1, ArrDate), DepDate, ID
      from cte
      where ArrDate < DepDate
     )
select Name, ArrDate, ID
from cte;

如果跨度超過100天,則可以設置最大遞歸選項。

另一種選擇是與Cross Apply一起使用的臨時計數表

Select A.Name
      ,B.Date
      ,A.ID
 From  YourTable A
 Cross Apply (
                Select Top (DateDiff(DAY,A.[ArrDate],A.[DepDate])+1) Date=DateAdd(DAY,-1+Row_Number() Over (Order By (Select Null)),A.[ArrDate])  
                From  master..spt_values n1,master..spt_values n2
                ) B

返回

Name    Date        ID
A       2016-03-29  100
A       2016-03-30  100
A       2016-03-31  100
A       2016-04-01  100
A       2016-04-02  100
B       2016-05-10  250
B       2016-05-11  250
B       2016-05-12  250

您可以使用日歷或日期表來進行此類操作。

您可以使用公共表表達式生成日期的臨時表,只需:

declare @fromdate date = '20160101'
declare @thrudate date = '20171231'
;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 t.Name, d.Date, t.Id
from t
  inner join dates d
    on d.date >= t.arrdate
   and d.date <= t.depdate

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

收益:

+------+------------+-----+
| Name |    Date    | Id  |
+------+------------+-----+
| A    | 2016-03-29 | 100 |
| A    | 2016-03-30 | 100 |
| A    | 2016-03-31 | 100 |
| A    | 2016-04-01 | 100 |
| A    | 2016-04-02 | 100 |
| B    | 2016-05-10 | 250 |
| B    | 2016-05-11 | 250 |
| B    | 2016-05-12 | 250 |
+------+------------+-----+

對於內存中只有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]);
/* query */
select t.Name, d.Date, t.Id
from t
  inner join dates d
    on d.date >= t.arrdate
   and d.date <= t.depdate

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

收益:

+------+------------+-----+
| Name |    Date    | Id  |
+------+------------+-----+
| A    | 2016-03-29 | 100 |
| A    | 2016-03-30 | 100 |
| A    | 2016-03-31 | 100 |
| A    | 2016-04-01 | 100 |
| A    | 2016-04-02 | 100 |
| B    | 2016-05-10 | 250 |
| B    | 2016-05-11 | 250 |
| B    | 2016-05-12 | 250 |
+------+------------+-----+

數字和日歷表參考:

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM