2017-12-18 317 views
2

我試圖計算一行中「出現」a在兩個日期之間的範圍內並將其按月份分組的次數。獲取每個時間行的計數出現在兩個日期之間的範圍

所以,讓我們說,我有看起來像這樣的行:

Name | StartDate  | EndDate 
-----------|-----------------|------------ 
    Mathias | 2017-01-01  | 2017-04-01 
    Lucas | 2017-01-01  | 2017-04-01 

我想獲得,顯示多少條記錄在查詢中兩個日期之間存在的輸出,所以像下面的輸出:

Count | Year   | Month 
-----------|-----------------|------------ 
    2  | 2017   | 1 
    2  | 2017   | 2 
    2  | 2017   | 3 
    2  | 2017   | 4 
    0  | 2017   | 5 
    0  | 2017   | 6 

我已經試過是:

SELECT COUNT(*) as COUNT, YEAR(StartDate) YEAR, MONTH(StartDate) MONTH 
FROM NamesTable 
WHERE Start >= '2017-01-01 00:00:00' 
AND Slut <= '2017-06-01 00:00:00' 
group by YEAR(StartDate), MONTH(StartDate) 

哪裏,這是給我的EXP ected輸出:

Count | Year   | Month 
-----------|-----------------|------------ 
    2  | 2017   | 1 
    0  | 2017   | 2 
    0  | 2017   | 3 
    0  | 2017   | 4 
    0  | 2017   | 5 
    0  | 2017   | 6 

由於分組由「開始日期」,我怎麼能算在本月行的每一個它擴展跨越?

+0

是否有一個起始日期爲每月,以便選擇不同的StatDate將提供所需月份的完整列表? – Turo

+0

每條記錄​​都有一個開始日期和結束日期,但這些記錄可能會重疊,因爲一條記錄可能會延長1個月以上。希望它是有道理的 –

回答

0

你需要一個表的範圍幾個月

allMonths

+---------+------------+------------+ 
| monthId | StartDate | EndDate | 
+---------+------------+------------+ 
|  1 | 2017-01-01 | 2017-01-02 | 
|  2 | 2017-01-02 | 2017-01-03 | 
|  3 | 2017-01-03 | 2017-01-04 | 
|  4 | 2017-01-04 | 2017-01-05 | 
|  5 | 2017-01-05 | 2017-01-06 | 
|  6 | 2017-01-06 | 2017-01-07 | 
|  7 | 2017-01-07 | 2017-01-08 | 
|  8 | 2017-01-08 | 2017-01-09 | 
|  9 | 2017-01-09 | 2017-01-10 | 
|  10 | 2017-01-10 | 2017-01-11 | 
|  11 | 2017-01-11 | 2017-01-12 | 
|  12 | 2017-01-12 | 2018-01-01 | 
+---------+------------+------------+ 

那麼你的查詢是:

SELECT am.startDate, COUNT(y.Name) 
FROM allMonths am 
LEFT JOIN yourTable y 
    ON am.StartDate <= y.EndDate 
AND am.EndDate >= y.StartDate 
GROUP BY am.startDate 

注:您需要檢查邊界情況。也許你需要更改>=>或將EndDate更改爲月份的最後一天。

+0

你的解決方案可能會工作,但我不想創建第二個表,只是幾個月,像feb可以變化,對不對?必須有一種方法來創建一個存儲的專業或視圖來完成這項工作。 –

+0

您可以使用類似於[** this **]的查詢來創建cte(https://stackoverflow.com/questions/1378593/get-a-list-of-dates-between-two-dates-using-a功能),以便您即時創建日期。但是創建一個有幾個月的表並不貴,100年只需要1200行 –

+0

您可以使用前面的查詢來獲取'startDate'和[** EOMONTH **](https://docs.microsoft.com/en-us/sql/t-sql/functions/emonth-transact-sql)得到'endDate' –

0

所以,我落得這樣做有點像胡安·卡洛斯提出,但不是創建一個表我CTE由它代替了一個更簡潔的方法:

Declare @todate datetime, @fromdate datetime, @firstOfMonth datetime, @lastOfMonth datetime 
Select 
@fromdate='2017-01-11', 
@todate='2017-12-21', 
@firstOfMonth = DATEADD(month, DATEDIFF(month, 0, @fromdate), 0), ----YEAR(@fromdate) + MONTH(@fromdate) + DAY(1), 
@lastOfMonth = DATEADD(month, ((YEAR(@fromdate) - 1900) * 12) + MONTH(@fromdate), -1) 

;with MonthTable (MonthId, StartOfMonth, EndOfMonth) as 
(
     SELECT MONTH(@firstOfMonth) as MonthId, @firstOfMonth as StartOfMonth, @lastOfMonth as EndOfMonth 
     UNION ALL 
     SELECT MONTH(DATEADD(MONTH, 1, StartOfMonth)), DATEADD(MONTH, 1, StartOfMonth), DATEADD(MONTH, 1, EndOfMonth) 
     FROM MonthTable 
     WHERE StartOfMonth <= @todate 
) 

SELECT am.StartOfMonth, COUNT(y.Start) as count 
FROM MonthTable am 
left JOIN clientList y 
    ON y.Start <= am.StartOfMonth 
    AND y.End >= am.EndOfMonth 
GROUP BY am.StartOfMonth 
+0

您需要將'COUNT(*)'更改爲'COUNT(y.start)'類似的東西'否則您將在未得到結果時得到1。 –

+0

是的,我注意到這一點,並作出了改變,謝謝:-) –

相關問題