Twoje istniejące zapytanie można zredukować do:
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)
Aby wyświetlić co godzinę, w tym te, dla których nie ma danych, musisz połączyć zewnętrzne z tabelą zawierającą wszystkie godziny, dla których chcesz uzyskać dane. Możesz zbudować taką tabelę w swoim zapytaniu za pomocą 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
Jednak traktowanie grup, dla których nie istnieją żadne dane, jest tak naprawdę kwestią logiki biznesowej, którą najlepiej umieścić w warstwie dostępu do danych, a nie w samej bazie danych:w rzeczywistości powinno być trywialne, aby aplikacja używała wartości zerowej za każdym razem, gdy jest godzina. nieobecny.