2010-08-30 7 views
9
table de base de données

comme celui-cinombre return 0 avec le groupe mysql par

============================ 
= suburb_id | value 
= 1   | 2 
= 1   | 3 
= 2   | 4 
= 3   | 5 

requête est

SELECT COUNT(suburb_id) AS total, suburb_id 
    FROM suburbs 
where suburb_id IN (1,2,3,4) 
GROUP BY suburb_id 

cependant, alors que je lance cette requête, il ne donne pas COUNT (suburb_id) = 0 lorsque suburb_id = 0 parce que dans le tableau de banlieue, il n'y a pas suburb_id 4, je veux que cette requête renvoie 0 pour suburb_id = 4, comme

============================ 
= total  | suburb_id 
= 2   | 1 
= 1   | 2 
= 1   | 3 
= 0   | 4 
+0

Avez-vous une autre table avec des informations pour toutes les banlieues? Ou est surburb 4 Sir n'apparaissant pas dans cette base de données? – Powerlord

Répondre

10

Un GROUP BY a besoin de lignes pour fonctionner, donc si vous n'avez pas de ligne pour une certaine catégorie, vous n'obtiendrez pas le nombre. Pensez à la clause where comme limitant les lignes source avant qu'elles ne soient regroupées. La clause where ne fournit pas de liste de catégories à regrouper.

Ce que vous pouvez faire est d'écrire une requête pour sélectionner les catégories (banlieues) puis faire le compte dans une sous-requête. (Je ne suis pas sûr de ce que le soutien de MySQL en est comme)

Quelque chose comme:

SELECT 
    s.suburb_id, 
    (select count(*) from suburb_data d where d.suburb_id = s.suburb_id) as total 
FROM 
    suburb_table s 
WHERE 
    s.suburb_id in (1,2,3,4) 

(MSSQL, excuses)

+0

+1 pour un cas simple, mais lorsque vous avez besoin de combiner plusieurs requêtes plus compliquées, veuillez consulter ma réponse. – Upgradingdave

+0

C'était exactement ce que je cherchais! – thenetimp

1

Requête:

select case 
     when total is null then 0 
     else total 
     end as total_with_zeroes, 
     suburb_id 
from (SELECT COUNT(suburb_id) AS total, suburb_id 
     FROM suburbs 
     where suburb_id IN (1,2,3,4) 
    GROUP BY suburb_id) as dt 
+1

Parce qu'il n'y a aucun enregistrement avec 'suburb_id' étant 4, la requête interne ne retournera pas une valeur NULL pour l'expression CASE à capturer. –

4

Ce:

SELECT id, COUNT(suburb_id) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 
LEFT JOIN 
     suburbs s 
ON  s.suburb_id = ids.id 
GROUP BY 
     id 

ou ceci:

SELECT id, 
     (
     SELECT COUNT(*) 
     FROM suburb 
     WHERE suburb_id = id 
     ) 
FROM (
     SELECT 1 AS id 
     UNION ALL 
     SELECT 2 AS id 
     UNION ALL 
     SELECT 3 AS id 
     UNION ALL 
     SELECT 4 AS id 
     ) ids 

Cet article compare les performances des deux approches:

, mais il importe peu dans votre cas, que vous interrogez seulement 4 enregistrements.

+0

Puke. Mais correct. Mysql a tellement de fonctionnalités géniales "non standard", comment se fait-il qu'il n'ait pas encore de générateur de série?! btw, pour au moins une brièveté de code, vous pouvez supprimer le 'ALL' de votre' UNION's (toutes les valeurs sont uniques et déjà ordonnées, donc le résultat sera le même avec juste 'UNION') et supprimer tout sauf le premier 'AS ID'. Et vous pouvez l'aligner: 'FROM (SELECT 1 AS ID UNION SELECT 2 UNION SELECT 3 UNION SELECT 4) ids'. – Bohemian

1

La solution de geofftnz fonctionne très bien si toutes les conditions sont simples comme dans ce cas. Mais j'ai juste dû résoudre un problème similaire pour générer un rapport où chaque colonne du rapport est une requête différente. Lorsque vous devez combiner les résultats de plusieurs instructions select, alors quelque chose comme ça peut fonctionner.

Vous devrez peut-être créer cette requête par programmation. L'utilisation de jointures à gauche permet à la requête de renvoyer des lignes même s'il n'y a pas de correspondance avec suburb_id avec un identifiant donné. Si votre base de données supporte (dont la plupart ne), vous pouvez utiliser IFNULL pour remplacer null avec 0:

select IFNULL(a.count,0), IFNULL(b.count,0), IFNULL(c.count,0), IFNULL(d.count,0) 
from (select count(suburb_id) as count from suburbs where id=1 group by suburb_id) a, 
left join (select count(suburb_id) as count from suburbs where id=2 group by suburb_id) b on a.suburb_id=b.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=3 group by suburb_id) c on a.suburb_id=c.suburb_id 
left join (select count(suburb_id) as count from suburbs where id=4 group by suburb_id) d on a.suburb_id=d.suburb_id; 

La bonne chose à ce sujet est que (le cas échéant) chaque « join gauche » peut utiliser un peu différent (peut-être assez complexe) requête.

Avertissement: pour les grands ensembles de données, ce type de requête aurait pu ne pas fonctionner très bien (je ne vous écris pas assez sql savoir sans enquêter plus loin), mais au moins il devrait donner des résultats utiles ;-)