2011-05-26 18 views
5

Benim sql sorgumda, günün her Saatinde sipariş sayısını sayarım. Benim sorgu şuna benzer:Tüm gün boyu

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 

Benim sorunum sorgu dbo.Orders.Date sadece varolan Saat döndürür olmasıdır. Örneğin
:

Number Hour 
12   3 
12   5 

böyle her saat dönmek istiyorum:

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

herkes fikri var mı bunu gerçekleştirmek nasıl?

cevap

6

her saat oluşturmak için ortak bir tablo ifade kullanın, ardından bir sonuç almak için gruplandırılmış toplamları katılmak bıraktı.

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

olumlu değil Bu mycte oluştururken sözdizimi, ancak teori doğru ses ... – DRapp

+0

Ben CTE kısmı cevabı yüklemeden önce kontrol edildi. İşe yaramış görünüyor: D –

0

Eksik saatleri eklemek için CTE ve boşlukları doldurmak için orijinal sorgunuzu JOIN kullanabilirsiniz.

SQL Bildirimi

;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  

Testi Senaryo

;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 'numaralar tablo' (örneğin SQL, Auxiliary table of numbers) veritabanınızda olması genel oldukça yararlı bir şey olduğunu; Burada bir tane oluşturursanız, sayı tablonuzdan 0 ile 23 arasındaki tüm satırları seçebilir, sonuçlarınızla karşılaştırmadan solabilirsiniz ve istediğiniz sonuçları, bu sorgu için özel bir CTE veya benzeri oluşturma ihtiyacı olmadan elde edersiniz.

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 

(Ben netlik için örnek başına bu ifadeli ettik ama pratikte denemek ve performansını maksimize etmek katılmak kriterlerde bir işlevi koyarak önleyeceğini.) Sql-sunucu