2010-03-19 13 views
8

Ho tabella MySQLMySQL: riempire i campi vuoti con zeri quando si utilizza GROUP BY

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

che contiene statistiche sui visitatori del sito.
Per ottenere visite orarie Io uso

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

che mi dà

| 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  | 

E mi piacerebbe ottenere seguente:

| 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  | 

Come devo modificare la query per ottenere tale risultato (con una query mysql, senza creare tabelle temporanee)?
È possibile ottenere tale risultato con una query MySQL?

+0

SaltLake, pensi di accettare una risposta? –

+0

Marcus, la tua soluzione funziona ma non nel modo in cui voglio che sia. Sono interessato alla soluzione con una query SQL e senza creare e riempire altre tabelle. – SaltLake

risposta

4

Ho finalmente trovato la risposta. Forse sono pazzo, ma funziona.

 
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 

Una query MySQL come desiderato.

8

Creare un'altra tabella con una sola colonna,

CREATE TABLE hours_list (
    hour int NOT NULL PRIMARY KEY 
) 

riempirla di tutte le 24 ore.

Quindi fare un join su quella tabella per riempire gli zeri.

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

Questa è solo la parte "perché non sta tornando". La risposta di Marcus copre la parte 'come'.

Lo SQL

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

Ottiene il conteggio dei record per ora, per i timestamp presenti nella tabella

Non dà i dettagli di ciò che non è presente nella tabella. Poiché non vi è alcun recors per il timestamp corrispondente all'ora 8 (dal tuo esempio), l'SQL non restituisce alcun record.

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); 

Grazie! Fatto! Da 2 tabelle, clic e viste, uniti .. funziona. ajaxel.com