2017-04-14 84 views
1

嗨我想運行一個查詢來爲每個項目,我有兩個日期之間的每個月返回一個行。見例如數據:每個項目的2個日期之間的月份

Project Start  End 
1  1/1/2015 3/1/2015 
2  2/1/2015 4/1/2015 

末所需數據:

Project Month 
1  1/1/2015 
1  2/1/2015 
1  3/1/2015 
2  2/1/2015 
2  3/1/2015 
2  4/1/2015 

我有幾個項目,將需要一個查詢來同時對所有的人都這樣做。我如何在SQL Server中執行此操作?

回答

1

另一種選擇是CROSS APPLY有一個特設的理貨表

Select A.Project 
     ,Month = B.D 
From YourTable A 
Cross Apply (
       Select Top (DateDiff(MONTH,A.Start,A.[End])+1) D=DateAdd(Month,-1+Row_Number() Over (Order By(Select null)),A.Start) 
       From master..spt_values 
      ) B 

返回

Project Month 
1  2015-01-01 
1  2015-02-01 
1  2015-03-01 
2  2015-02-01 
2  2015-03-01 
2  2015-04-01 
0

生成時間series從鏈接獲取幫助。

然後

之間 使用連接時間選擇--something FROM表1一個 /類型的/JOIN表2 B關於BETWEEN a.field2與a.field3 b.field2

1

這是簡單如果您有或創建了幾個月的表:

create table dbo.Months([Month] date primary key); 
declare @StartDate  date = '20100101' 
     ,@NumberOfYears int = 30; 

insert dbo.Months([Month],MonthEnd) 
    select top (12*@NumberOfYears) 
     [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate) 
    from master.dbo.spt_values; 

如果你真的不希望有一個表個月,你可以使用一個cte這樣的:

declare @StartDate  date = '20100101' 
     ,@NumberOfYears int = 10; 

;with Months as (
    select top (12*@NumberOfYears) 
    [Month] = dateadd(month, row_number() over (order by number) -1, @StartDate) 
    from master.dbo.spt_values 
) 

然後查詢它像這樣:

select 
    t.Project 
    , m.Month 
from t 
    inner join dbo.Months m 
    on m.Month >= t.Start 
    and m.Month <= t.[End] 

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

回報:

+---------+------------+ 
| Project | Month | 
+---------+------------+ 
|  1 | 2015-01-01 | 
|  1 | 2015-02-01 | 
|  1 | 2015-03-01 | 
|  2 | 2015-02-01 | 
|  2 | 2015-03-01 | 
|  2 | 2015-04-01 | 
+---------+------------+ 

日曆和數字表參考:

1

我個人很喜歡爲這種事情理貨表。這是t-sql的瑞士軍刀。

我爲此在我的系統上創建了一個視圖。如果你不想創建一個視圖,你可以隨時輕鬆地使用這些ctes,你需要一個理貨表。

create View [dbo].[cteTally] as 

WITH 
    E1(N) AS (select 1 from (values (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))dt(n)), 
    E2(N) AS (SELECT 1 FROM E1 a, E1 b), --10E+2 or 100 rows 
    E4(N) AS (SELECT 1 FROM E2 a, E2 b), --10E+4 or 10,000 rows max 
    cteTally(N) AS 
    (
     SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) FROM E4 
    ) 
select N from cteTally 
GO 

現在我們只需要您的示例數據在表中。

創建表#Projects ( 項目INT ,開始日期時間 ,結束日期日期時間 )

插入#Projects 選擇1, '1/1/2015', '2015年3月1日' 工會全部 選擇2,'2/1/2015','4/1/2015'

在這裏,我們到了真正的問題,這是檢索您的信息。通過示例數據和視圖,這變得非常簡單。

select p.* 
    , NewMonth = DATEADD(MONTH, t.N - 1, p.Start) 
from #Projects p 
join cteTally t on t.N <= DATEDIFF(MONTH, p.Start, p.EndDate) + 1 
order by p.Project 
    , t.N 
相關問題