2011-05-26 82 views
5

在我的sql查詢中,我計算了每天每小時的訂單數量。我的查詢看起來是這樣的:每天的所有時間

SELECT COUNT(dbo.Uputa.ID),{ fn HOUR(dbo.Orders.Date) } AS Hour 
FROM  Orders  
WHERE dbo.Orders.Date BETWEEN '2011-05-01' AND '2011-05-26' 
GROUP BY { fn HOUR(dbo.Orders.Date) } 
ORDER BY Hour 

我的問題是查詢只返回dbo.Orders.Date中的現有小時數。
例如:

Number Hour 
12   3 
12   5 

我想回到所有時間是這樣的:

Number  Hour 
    0   0 
    0   1 
    0   2 
    12   3 
    0   4 
    12   5 
    ... 
    0   23 

有誰知道知道如何做到這一點?

回答

6

使用公用表表達式來創建的所有時間,然後離開你的加入分組彙總得到的結果。

with mycte as 
(
    SELECT 0 AS MyHour 
    UNION ALL 
    SELECT MyHour + 1 
    FROM mycte 
    WHERE MyHour + 1 < 24 
) 
SELECT mycte.MyHour, COALESCE(OrderCount,0) FROM mycte 
LEFT JOIN 
(
    SELECT COUNT(dbo.Uputa.ID) AS OrderCount,{ fn HOUR(dbo.Orders.Date) } AS MyHour 
    FROM Orders  
    WHERE dbo.Orders.Date BETWEEN '2011-05-01' AND '2011-05-26' 
    GROUP BY { fn HOUR(dbo.Orders.Date) } 
) h 
ON 
    h.MyHour = mycte.MyHour; 
+0

不積極的SQL服務器的語法創建mycte,但理論聲音正確... – DRapp 2011-05-26 10:54:07

+0

在我上傳答案之前檢查了CTE部分。看起來有效:D – 2011-05-26 12:17:03

0

您可以使用CTE將缺少的小時數和JOIN這些與原始查詢一起填入空白處。

SQL語句

;WITH q (Number, Hour) AS (
    SELECT 0, 1 
    UNION ALL 
    SELECT q.Number, q.Hour + 1 
    FROM q 
    WHERE q.Hour < 23 
) 
SELECT COALESCE(o.Number, q.Number) 
     , q.Hour 
FROM q 
     LEFT OUTER JOIN (
      SELECT COUNT(dbo.Uputa.ID),{ fn HOUR(dbo.Orders.Date) } AS Hour 
      FROM  Orders  
      WHERE dbo.Orders.Date BETWEEN '2011-05-01' AND '2011-05-26' 
      GROUP BY { fn HOUR(dbo.Orders.Date) } 
     ) o ON o.Hour = q.Hour 
ORDER BY 
     q.Hour  

測試腳本

;WITH Orders (Number, Hour) AS (
    SELECT 12, 3 
    UNION ALL SELECT 12, 5 
) 
, q (Number, Hour) AS (
    SELECT 0, 1 
    UNION ALL 
    SELECT q.Number, q.Hour + 1 
    FROM q 
    WHERE q.Hour < 23 
) 
SELECT COALESCE(o.Number, q.Number) 
     , q.Hour 
FROM q 
     LEFT OUTER JOIN Orders o ON o.Hour = q.Hour 
1

A「號碼錶」(SQL, Auxiliary table of numbers例如)一般相當有您的數據庫中有用的東西;如果您在此處創建一個,則可以從數字表中選擇0到23之間的所有行,然後將其與您的結果進行加入,然後您將得到所需的結果,而無需爲此查詢創建自定義CTE或類似程序。

SELECT COUNT(dbo.Uputa.ID),n.number AS Hour 
FROM  (select number from numbers where number between 0 and 23) n 
      left join Orders o on n.number={ fn HOUR(dbo.Orders.Date) } 
WHERE dbo.Orders.Date BETWEEN '2011-05-01' AND '2011-05-26' 
GROUP BY n.number 
ORDER BY n.number 

(我這個措辭根據您的例子爲清楚起見,但在實踐中我會盡量避免把一個函數在連接標準,以最大限度地提高性能。)

相關問題