2010-04-28 13 views
6

Sono sicuro che questa risposta è molto semplice, ma non riesco a trovarla (non sono sicuro su cosa cercare!) . Un conteggio/gruppo per query standard può essere simile al seguente:MYSQL: COUNT con GROUP BY, LEFT JOIN e WHERE la clausola non restituisce valori zero

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 

e questo funziona come previsto, restituendo 0 se non vengono trovate righe. Tuttavia:

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

funziona solo se esiste almeno una riga in Table_1 e fallisce sprecando restituendo un risultato vuoto impostato se ci sono zero righe. Mi piacerebbe molto questo per restituire 0! Qualcuno mi illumina su questo? La birra può essere fornita in cambio se si è a Londra ;-)

risposta

4

Il motivo per cui restituisce zero righe è che si sta raggruppando su un valore in table_1. SINC Non ci sono valori in table_1, non ci sono righe da restituire. Detto in altro modo, se si ritorna t1.any_col nella query dalla GROUP BY in questo modo:

SELECT `t1`.`any_col`, COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 

Cosa visualizzare per t1.any_col quando non c'erano le righe? L'unico modo per ottenere ciò che vuoi è unire i tuoi risultati con un'altra query che non verifica alcuna riga in table_1. In questo esempio, sto usando la vista INFORMATION_SCHEMA semplicemente per avere qualcosa contro cui posso interrogare.

SELECT COUNT(`t2`.`name`) 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col` 
UNION ALL 
SELECT 0 
FROM INFORMATION_SCHEMA.TABLES 
Where Not Exists(Select 1 From `table_1`) 
LIMIT 1 
+0

Perché il primo esempio funziona bene allora? Tutto ciò che manca è la clausola WHERE, non ci possono essere ancora righe e questo funzionerà bene ... –

+0

@Paul Norman - Il primo esempio funziona perché chiaramente ci sono righe nella tabella_1. Il terzo esempio non funziona perché apparentemente non ci sono righe in table_1 che hanno un valore 123 per 'another_column'. Se la query senza il raggruppamento non restituisce alcuna riga, non restituirà le righe con il raggruppamento. – Thomas

3

Ecco la soluzione migliore:

SELECT COUNT(*) FROM 
(SELECT `t2`.`name` 
FROM `table_1` `t1` 
    LEFT JOIN `table_2` `t2` ON `t1`.`key_id` = `t2`.`key_id` 
WHERE `t1`.`another_column` = 123 
GROUP BY `t1`.`any_col`) tmp 

Hai solo bisogno di avvolgere intorno SELECT COUNT(*) la query.

Il problema è che COUNT() cambia dal significato "concedi un conteggio delle righe nel set di risultati" a una funzione di aggregazione che significa "dammi un conteggio delle righe per ogni gruppo che corrisponde ai miei criteri" quando viene utilizzato con il GROUP BY clausola. Nel tuo caso, poiché non ci sono righe per il gruppo dove another_column = 123, non viene restituito nulla.

Se lo si avvolge in un altro SELECT COUNT(*), si sta ripetendo "datemi il conteggio delle righe nel set di risultati".

Nella prima query, COUNT() funziona con GROUP BY. Ma senza specificare alcun criterio, stai ricevendo almeno una riga restituita da table_1. Poiché non ci sono record tabella_2 corrispondenti, NULL restituisce 0 per COUNT(). Non usare la prima query. Anche se restituisce ciò che ti aspetti, è solo per caso. Affinché la query sia significativa, è necessario specificare i criteri per t1.alterna_colonna nella clausola WHERE.

La seconda query funziona perché si richiede un conteggio delle righe del set di risultati. Dato che non ci sono righe dove t1.another_column = 123, ci sono 0 righe restituite, e COUNT() valuta a 0.

+0

Questo purtroppo mi dice solo quanti "gruppi" unici ci sono. Quindi se c'è un solo valore 'any_col' in' table_1', ma 5 righe di dati dove 'any_col' = 5 restituisce 1, non 5 come richiesto (perché lo SELECT nidificato restituirà solo una riga). –

+0

@Paul, si prega di aggiornare il browser. Ho risolto questo. Si noti che COUNT() viene utilizzato solo nella query esterna. –

+0

Ho fatto questo cambiamento da solo, ma continuo a pensare (o meglio ho provato) che GROUP BY nella query nidificata significa che verrà restituita una sola riga se gli unici dati nella tabella hanno un solo valore 'any_col' (cioè se ogni riga ha 'any_col' = 5, allora la selezione nidificata restituirà solo una riga - come ci si aspetterebbe - e quindi ne consegue che il conteggio di questi dati produce solo 1, non il 5 richiesto. La soluzione di cui sopra funziona comunque un trattamento, mai pensato! Grazie per tutto l'aiuto. È difficile essere chiari in questa piccola scatola! –

Problemi correlati