![](/img/trans.png)
[英]How to change start date in a table to a pair of start date and end date using 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.