2014-02-06 44 views
0

我有以下SQL查詢計數訂單,並按每個日期(日期)進行分組。SQL計數記錄,按日期分組並填寫缺失日期?

因此,下面的結果:

01/02/2014 = 10 
02/02/2014 = 2 
05/02/2014 = 7 
07/02/2014 = 4 

查詢:

SELECT TOP(@NumberOfRecords) DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) AS Date,  COUNT(DISTINCT ID) AS Count 
      FROM OrderSpecs 
      GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) 
      ORDER BY Date DESC 

我的問題是,怎樣才能讓我的查詢填寫任何在兩者之間缺少的日期,並設置計數值爲0?

例期望的結果:

01/02/2014 = 10 
    02/02/2014 = 2 
    03/02/2014 = 0 
    04/02/2014 = 0 
    05/02/2014 = 7 
    06/02/2014 = 0 
    07/02/2014 = 4 

你取出時間閱讀本非常感謝。

回答

1
DECLARE @mindate DATETIME 
DECLARE @maxdate DATETIME 
DECLARE @diff INT 
SELECT @maxdate = MAX(addeddate), @mindate = MIN(addeddate) FROM OrderSpecs 
SET @diff = DATEDIFF(DAY, @mindate,@maxdate) 
;WITH cte(dt,level) 
AS 
(
    SELECT @mindate AS dt, 0 AS level 
    UNION ALL 
    SELECT DATEADD(day,1,cte.dt),level + 1 from cte WHERE level < @diff 
) 
SELECT dt,c FROM cte 
LEFT JOIN 
(
    SELECT DATEADD(dd, 0, DATEDIFF(dd, 0,AddedDate)) AddedDt, COUNT(ID) AS c 
    FROM OrderSpecs 
    GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0,AddedDate)) 
) tab 
ON cte.dt = tab.AddedDt 
OPTION (MaxRecursion 32767); 

CTE被寫入來生成日期範圍內的所有日期。通過這個聚合結果集的LEFT JOIN完成。

免責聲明:如果日期範圍是更多的32767天

+0

謝謝你,我真的很感激你回到我身邊。一個問題是,dt列正在返回第一個日期記錄的時間部分並將其應用於所有其他日期。即** 20/12/2013 14:42:56 **,那麼下一個記錄是** 21/12/2013 14:42:56 **。您填寫空白日期的解決方案正在運行,但是,第一個項返回時,所有計數結果爲空,第一個計數結果項爲1.我要查找的結果應該是** Date:20/12/2013 Count :4 **,**日期:21/12/2013計數:0 **,**日期:22/12/2013計數:7 **。 – RobHurd

+0

已根據您的意見對我的答案進行了一些修改。解決方案是假設AddedDate是日期字段,但實際上它是一個日期時間字段,我想這是意想不到的結果。讓我知道編輯工作與否! –

+0

謝謝修改Dipendu保羅。我真的很感謝你的幫助。最初你的修正案沒有奏效,但是我編輯了** DECLARE mindate DATETIME **&** DECLARE maxdate DATETIME **到** DATE **,現在它看起來像預期的那樣工作。我需要更徹底地檢查返回的結果,但在表面上看起來工作得很好。我無法對你的幫助表示感謝。 – RobHurd

0

你可以沿着這條線做些事情。我沒有對它進行徹底的測試,但是原則上,如果你正在組織工會,它會拋出額外的費用。您可能需要對輸出做一個爲了把它放在正確的順序

SELECT SS1.Date, Count 
FROM 
( 
DECLARE @mindate Date 
DECLARE @maxdate Date 
WITH DateTable 
AS 
(
    SELECT CAST(@mindate as Date) AS [DATE] 
    UNION ALL 
    SELECT DATEADD(dd, 1, [DATE]) FROM DateTable 
    WHERE DATEADD(dd, 1, [DATE]) BETWEEN @mindate AND @maxdate 
) 
SELECT dt.[DATE], 0 [Count] FROM [DateTable] dt 
UNION ALL 

TOP(@NumberOfRecords) DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) AS Date,   COUNT(DISTINCT ID) AS Count 
     FROM OrderSpecs 
     GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) 
     ORDER BY Date DESC 
) SS1 
ORDER BY [Date] 

難道你知道你可以傳遞作爲種子日期開始和結束日期?

+0

我收到此錯誤'終止聲明此查詢是行不通的。在聲明完成之前,最大遞歸100已經用完了。 –

+0

您的日期範圍有多寬?我的猜測是超過100天? - 雖然,我喜歡@peterm解決方案更多 – owen79

+0

它是120天寬 –

2

如果發出了很多這樣的疑問,那麼你可以創建一個包含所有日曆日期

CREATE TABLE calendar([date] DATE NOT NULL PRIMARY KEY); 

日曆表,然後使用外連接

SELECT TOP(@NumberOfRecords) 
     c.Date, COALESCE(o.Count, 0) Count 
    FROM Calendar c LEFT JOIN 
(
    SELECT DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) AS Date, 
     COUNT(DISTINCT ID) AS Count 
    FROM OrderSpecs 
    GROUP BY DATEADD(dd, 0, DATEDIFF(dd, 0, AddedDate)) 
) o 
    ON c.Date = o.Date 
ORDER BY Date DESC 

輸出:

 
|  DATE | COUNT | 
|------------|-------| 
| 2014-02-07 |  4 | 
| 2014-02-06 |  0 | 
| 2014-02-05 |  7 | 
| 2014-02-04 |  0 | 
| 2014-02-03 |  0 | 
| 2014-02-02 |  2 | 
| 2014-02-01 | 10 | 

這裏是SQLFiddle d emo

+0

感謝您回到我身邊,我感謝您提供您的解決方案。我不是特別想要創建一個充滿日期的表的路線。但我明白你來自哪裏。 – RobHurd

+0

@RobHurd你很受歡迎。只要確保您在生產中獲得最佳性能。 – peterm