Весь час дня - PullRequest
       40

Весь час дня

5 голосов
/ 26 мая 2011

В моем запросе 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

Кто-нибудь есть идеи, как это сделать?

Ответы [ 3 ]

6 голосов
/ 26 мая 2011

Используйте общее табличное выражение для создания всех часов, а затем объедините сгруппированные итоги, чтобы получить результат.

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;
1 голос
/ 26 мая 2011

Таблица чисел (например, SQL, Вспомогательная таблица чисел ), как правило, очень полезна в вашей базе данных;если вы создадите одну из них здесь, вы можете выбрать все строки от 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

(я сформулировал это в соответствии с вашим примером для ясности, но на практике я бы постарался не включать функцию в критерии объединения для максимизации производительности.)

0 голосов
/ 26 мая 2011

Вы можете использовать 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...