2012-05-03 228 views
13

我試圖按小時使用情況從我的歷史記錄表中獲取報告。 history表是;MySQL Group By Hours

CREATE TABLE IF NOT EXISTS `history` (
`history_id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
`user_id` int(11) unsigned NOT NULL DEFAULT '0', 
`created` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, 
PRIMARY KEY (`history_id`), 
KEY `user_id` (`user_id`), 
KEY `created` (`created`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1 ; 

我想按HOURCOUNT在指定日期範圍內的所有記錄。

Hours   | Usage 
------------------------------------ 
00:00-01:00  |  5 
01:00-02:00  |  9 
02:00-03:00  |  0 (or NULL) 
03:00-04:00  |  20 
... 
... 
... 
22:00-23:00  |  11 
23:00-00:00  |  1 

我用了一個像這樣的查詢,但它不顯示所有小時。

SELECT 

CASE 
    WHEN HOUR(created) BETWEEN 0 AND 1 THEN '00:00 - 01:00' 
    WHEN HOUR(created) BETWEEN 1 AND 2 THEN '01:00 - 02:00' 
    WHEN HOUR(created) BETWEEN 2 AND 3 THEN '02:00 - 03:00' 
    WHEN HOUR(created) BETWEEN 3 AND 4 THEN '03:00 - 04:00' 
    WHEN HOUR(created) BETWEEN 4 AND 5 THEN '04:00 - 05:00' 
    WHEN HOUR(created) BETWEEN 5 AND 6 THEN '05:00 - 06:00' 
    WHEN HOUR(created) BETWEEN 6 AND 7 THEN '06:00 - 07:00' 
    WHEN HOUR(created) BETWEEN 7 AND 8 THEN '07:00 - 08:00' 
    WHEN HOUR(created) BETWEEN 8 AND 9 THEN '08:00 - 09:00' 
    WHEN HOUR(created) BETWEEN 9 AND 10 THEN '09:00 - 10:00' 
    WHEN HOUR(created) BETWEEN 10 AND 11 THEN '10:00 - 11:00' 
    WHEN HOUR(created) BETWEEN 11 AND 12 THEN '11:00 - 12:00' 
    WHEN HOUR(created) BETWEEN 12 AND 13 THEN '12:00 - 13:00' 
    WHEN HOUR(created) BETWEEN 13 AND 14 THEN '13:00 - 14:00' 
    WHEN HOUR(created) BETWEEN 14 AND 15 THEN '14:00 - 15:00' 
    WHEN HOUR(created) BETWEEN 15 AND 16 THEN '15:00 - 16:00' 
    WHEN HOUR(created) BETWEEN 16 AND 17 THEN '16:00 - 17:00' 
    WHEN HOUR(created) BETWEEN 17 AND 18 THEN '17:00 - 18:00' 
    WHEN HOUR(created) BETWEEN 18 AND 19 THEN '18:00 - 19:00' 
    WHEN HOUR(created) BETWEEN 19 AND 20 THEN '19:00 - 20:00' 
    WHEN HOUR(created) BETWEEN 20 AND 21 THEN '20:00 - 21:00' 
    WHEN HOUR(created) BETWEEN 21 AND 22 THEN '21:00 - 23:00' 
    WHEN HOUR(created) BETWEEN 22 AND 23 THEN '22:00 - 23:00' 
    WHEN HOUR(created) BETWEEN 23 AND 24 THEN '23:00 - 00:00' 
END AS `Hours`, 

COUNT(*) AS `usage` 
FROM history 
WHERE (created BETWEEN '2012-02-07' AND NOW()) 
GROUP BY 
    CASE 
    WHEN HOUR(created) BETWEEN 0 AND 1 THEN 1 
    WHEN HOUR(created) BETWEEN 1 AND 2 THEN 2 
    WHEN HOUR(created) BETWEEN 2 AND 3 THEN 3 
    WHEN HOUR(created) BETWEEN 3 AND 4 THEN 4 
    WHEN HOUR(created) BETWEEN 4 AND 5 THEN 5 
    WHEN HOUR(created) BETWEEN 5 AND 6 THEN 6 
    WHEN HOUR(created) BETWEEN 6 AND 7 THEN 7 
    WHEN HOUR(created) BETWEEN 7 AND 8 THEN 8 
    WHEN HOUR(created) BETWEEN 8 AND 9 THEN 9 
    WHEN HOUR(created) BETWEEN 9 AND 10 THEN 10 
    WHEN HOUR(created) BETWEEN 10 AND 11 THEN 11 
    WHEN HOUR(created) BETWEEN 11 AND 12 THEN 12 
    WHEN HOUR(created) BETWEEN 12 AND 13 THEN 13 
    WHEN HOUR(created) BETWEEN 13 AND 14 THEN 14 
    WHEN HOUR(created) BETWEEN 14 AND 15 THEN 15 
    WHEN HOUR(created) BETWEEN 15 AND 16 THEN 16 
    WHEN HOUR(created) BETWEEN 16 AND 17 THEN 17 
    WHEN HOUR(created) BETWEEN 17 AND 18 THEN 18 
    WHEN HOUR(created) BETWEEN 18 AND 19 THEN 19 
    WHEN HOUR(created) BETWEEN 19 AND 20 THEN 20 
    WHEN HOUR(created) BETWEEN 20 AND 21 THEN 21 
    WHEN HOUR(created) BETWEEN 21 AND 22 THEN 22 
    WHEN HOUR(created) BETWEEN 22 AND 23 THEN 23 
    WHEN HOUR(created) BETWEEN 23 AND 24 THEN 24 
END 

僅當存在任何記錄時才顯示。

Hours   | Usage 
------------------------------------ 
00:00-01:00  |  5 
01:00-02:00  |  9 
23:00-00:00  |  1 
+0

使用實際數據創建一個包含所有小時數和左連接的臨時表。 –

回答

22

現有查詢可以簡化爲:

SELECT CONCAT(HOUR(created), ':00-', HOUR(created)+1, ':00') AS Hours 
    ,  COUNT(*) AS `usage` 
FROM  history 
WHERE created BETWEEN '2012-02-07' AND NOW() 
GROUP BY HOUR(created) 

要顯示小時,包括那些沒有數據,就需要外,其所有小時表連接爲此你需要數據。您可以使用UNION在查詢中建立這樣一個表:

SELECT CONCAT(Hour, ':00-', Hour+1, ':00') AS Hours 
    ,  COUNT(created) AS `usage` 
FROM  history 
    RIGHT JOIN (
        SELECT 0 AS Hour 
     UNION ALL SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3 
     UNION ALL SELECT 4 UNION ALL SELECT 5 UNION ALL SELECT 6 
     UNION ALL SELECT 7 UNION ALL SELECT 8 UNION ALL SELECT 9 
     UNION ALL SELECT 10 UNION ALL SELECT 11 UNION ALL SELECT 12 
     UNION ALL SELECT 13 UNION ALL SELECT 14 UNION ALL SELECT 15 
     UNION ALL SELECT 16 UNION ALL SELECT 17 UNION ALL SELECT 18 
     UNION ALL SELECT 19 UNION ALL SELECT 20 UNION ALL SELECT 21 
     UNION ALL SELECT 22 UNION ALL SELECT 23 
)  AS AllHours ON HOUR(created) = Hour 
WHERE created BETWEEN '2012-02-07' AND NOW() OR created IS NULL 
GROUP BY Hour 
ORDER BY Hour 

然而,對於不存在數據組的治療是真正的業務邏輯的事情是最好的放在你的數據訪問層,而不是在數據庫本身:實際上,每當一小時不存在時,應用程序應該使用零值。

+1

您的第二個查詢仍然不會每小時顯示,只有在有記錄(或使用率> 0)時才顯示。我錯過了什麼嗎? –

+0

@BurakErdem:道歉,需要包括'創建IS NULL'的記錄(即在那個時間範圍內沒有歷史記錄的地方)。看到我上面的修改版本。 – eggyal

+0

這很好。非常感謝... –

0

給定一個表日誌與列TS,下面將給出平均每小時過去24小時(假設每小時至少有一個排)。

SELECT 
    FROM_UNIXTIME(TRUNCATE(UNIX_TIMESTAMP(`ts`)/3600, 0) * 3600) as h, 
    AVG(`value`) as v, 
    COUNT(*) as q 
FROM 
    Log 
GROUP BY 
    h 
ORDER BY 
    h desc 
LIMIT 
    24 

TS可以是時間戳或日期時間列而是任何AVG()將接受的。