2010-03-19 2 views
8

J'ai table MySQLMySQL: remplir les champs vides avec des zéros lors de l'utilisation GROUP BY

CREATE TABLE cms_webstat (
    ID int NOT NULL auto_increment PRIMARY KEY, 
    TIMESTAMP_X timestamp DEFAULT CURRENT_TIMESTAMP, 
    # ... some other fields ... 
) 

qui contient des statistiques sur les visiteurs du site.
Pour obtenir des visites par heure, j'utilise

SELECT 
    hour(TIMESTAMP_X) as HOUR 
    , count(*) AS HOUR_STAT 
FROM cms_webstat 
GROUP BY HOUR 
ORDER BY HOUR DESC 

qui me donne

| HOUR | HOUR_STAT | 
| 24 | 15  | 
| 23 | 12  | 
| 22 | 9  | 
| 20 | 3  | 
| 18 | 2  | 
| 15 | 1  | 
| 12 | 3  | 
| 9 | 1  | 
| 3 | 5  | 
| 2 | 7  | 
| 1 | 9  | 
| 0 | 12  | 

Je voudrais obtenir ce qui suit:

| HOUR | HOUR_STAT | 
| 24 | 15  | 
| 23 | 12  | 
| 22 | 9  | 
| 21 | 0  | 
| 20 | 3  | 
| 19 | 0  | 
| 18 | 2  | 
| 17 | 0  | 
| 16 | 0  | 
| 15 | 1  | 
| 14 | 0  | 
| 13 | 0  | 
| 12 | 3  | 
| 11 | 0  | 
| 10 | 0  | 
| 9 | 1  | 
| 8 | 0  | 
| 7 | 0  | 
| 6 | 0  | 
| 5 | 0  | 
| 4 | 0  | 
| 3 | 5  | 
| 2 | 7  | 
| 1 | 9  | 
| 0 | 12  | 

Comment dois-je modifier la requête pour obtenir un tel résultat (avec une requête mysql, sans créer de tables temporaires)?
Est-il possible d'obtenir un tel résultat avec une requête MySQL?

+0

SaltLake, pensez-vous que vous accepterez une réponse? –

+0

Marcus, votre solution fonctionne mais pas comme je le veux. Je suis intéressé par une solution avec une requête SQL et sans créer et remplir d'autres tables. – SaltLake

Répondre

4

J'ai finalement trouvé la réponse. Peut-être que je suis fou, mais cela fonctionne.

 
SELECT HOUR, max(HOUR_STAT) as HOUR_STAT FROM (
    (
     SELECT HOUR(TIMESTAMP_X) as HOUR, count(*) as HOUR_STAT 
     FROM cms_webstat 
     WHERE date(TIMESTAMP_X) = date(now()) 
    ) 
    UNION (SELECT 0 as HOUR, 0) 
    UNION (SELECT 1 as HOUR, 0) 
    UNION (SELECT 2 as HOUR, 0) 
    UNION (SELECT 3 as HOUR, 0) 
    UNION (SELECT 4 as HOUR, 0) 
    UNION (SELECT 5 as HOUR, 0) 
    UNION (SELECT 6 as HOUR, 0) 
    UNION (SELECT 7 as HOUR, 0) 
    UNION (SELECT 8 as HOUR, 0) 
    UNION (SELECT 9 as HOUR, 0) 
    UNION (SELECT 10 as HOUR, 0) 
    UNION (SELECT 11 as HOUR, 0) 
    UNION (SELECT 12 as HOUR, 0) 
    UNION (SELECT 13 as HOUR, 0) 
    UNION (SELECT 14 as HOUR, 0) 
    UNION (SELECT 15 as HOUR, 0) 
    UNION (SELECT 16 as HOUR, 0) 
    UNION (SELECT 17 as HOUR, 0) 
    UNION (SELECT 18 as HOUR, 0) 
    UNION (SELECT 19 as HOUR, 0) 
    UNION (SELECT 20 as HOUR, 0) 
    UNION (SELECT 21 as HOUR, 0) 
    UNION (SELECT 22 as HOUR, 0) 
    UNION (SELECT 23 as HOUR, 0) 
) 
AS `combined_table` 
GROUP BY HOUR 
ORDER BY HOUR DESC 

Une requête MySQL comme vous le souhaitez.

8

Créer une autre table avec une seule colonne,

CREATE TABLE hours_list (
    hour int NOT NULL PRIMARY KEY 
) 

Remplissez avec toutes les 24 heures. Ensuite, faites une jointure sur cette table pour remplir les zéros.

SELECT 
    hs.hour as HOUR, COUNT(ws.ID) AS HOUR_STAT 
FROM hours_list hs 
LEFT JOIN cms_webstat ws ON hs.hour = hour(ws.TIMESTAMP_X) 
GROUP BY hs.hour 
ORDER BY hs.hour DESC 
3

Ceci est juste la partie «pourquoi il ne revient pas». La réponse de Marcus couvre la partie "comment".

Le SQL

SELECT 
    hour(TIMESTAMP_X) as HOUR 
    , count(*) AS HOUR_STAT 
FROM cms_webstat 
GROUP BY HOUR 
ORDER BY HOUR DESC 

obtient le nombre des dossiers par heure, pour les horodateurs présents dans le tableau

Il ne donne pas les détails de ce qui ne figure pas dans le tableau. Comme il n'y a pas de recors pour l'horodateur correspondant à l'heure 8 (à partir de votre exemple) le SQL ne retourne aucun enregistrement.

0
$sql = 'SELECT g, MAX(v) AS v, MAX(c) AS c FROM ('; 
$sql .= '(SELECT DATE_FORMAT(viewed, \'%d.%m.%Y\') AS g, COUNT(1) AS v, 0 AS c FROM '.$this->prefix.'view WHERE campaignid IN ('.join(', ',$ids).') GROUP BY g)'; 
$sql .= ' UNION (SELECT DATE_FORMAT(clicked, \'%d.%m.%Y\') AS g, 0 AS v, COUNT(1) AS c FROM '.$this->prefix.'clicks WHERE campaignid IN ('.join(', ',$ids).') GROUP BY g)'; 
$today = strtotime("00:00:00"); 
for ($i=$today; $i>=time()-30*86400; $i-=86400) { 
    $sql .= ' UNION (SELECT \''.date('d.m.Y',$i).'\' AS g, 0 AS v, 0 AS c)'; 
} 
$sql .= ') AS tmp GROUP BY g ORDER BY g DESC'; 

$chart = DB::getAll($sql); 
p($chart); 

Merci! Fait le! A partir de 2 tables, clics et vues, jointes .. œuvres. ajaxel.com