2010-09-10 5 views
1

J'ai cette requête sql récupérer ID d'une table avec 3 colonnes: ID, Pays et âgesql requête compter les zéros

SELECT Country, 
(CASE 
WHEN AGE BETWEEN 0 AND 9 THEN '0-9' 
WHEN AGE BETWEEN 10 AND 19 THEN '10-19' 
WHEN AGE BETWEEN 20 AND 29 THEN '20-29' 
WHEN AGE BETWEEN 30 AND 39 THEN '30-39' 
WHEN AGE BETWEEN 40 AND 49 THEN '40-49' 
ELSE '50+' 
END) Age_Bins, COUNT (DISTINCT ID) 
FROM MYTABLE 
GROUP BY Country, Age_Bins; 

Les résultats que je reçois sont quelque chose comme:

UK '0-9' 7; 
UK '20-29' 14; 
etc... 

Mais ce que j'aimerais avoir, c'est aussi UK '10 -19 '0 (où il n'y a pas d'ID dans cette section d'âge). Comment le code sql peut-il être modifié en conséquence pour donner aussi des résultats avec des comptes zéro? Merci

Répondre

4

Vous pourrait créer chaque age-bin comme une colonne basée sur des cas, retournant 0 ou 1, et utiliser SUM() au lieu de COUNT()

select V.country, sum(V.Zero2Nine) as [0-9], sum(V.Ten2Nineteen) as [10-19] ... 
from 
(
    select country, 
    (case when age between 0 and 9 then 1 else 0 end) as Zero2Nine, 
    (case when age between 10 and 19 then 1 else 0 end) as Ten2Nineteen 
    from ... 
) as V 

group by V.country 
+0

J'aime cette solution, car elle semble simple, bien qu'elle n'utilise pas directement "COUNT". Cependant je ne sais pas si cela a des inconvénients par rapport à la première solution présentée ci-dessus. – francogrex

+0

J'utilise cette approche de colonne virtuelle tout le temps dans des applications du monde réel qui nécessitent des «bacs» ou des «compartiments». Il fonctionne rapidement et les résultats sont précis. La requête est simple à comprendre et à maintenir. Je ne connais aucun inconvénient. Pourquoi pas un vote? :-) – Tim

+0

Bien sûr. J'ai voté pour les deux solutions et je donne la meilleure réponse :) – francogrex

8

Idéalement, vous voulez une table de « bacs d'âge » et une table des pays à utiliser comme ceci:

select c.Country, b.age_bin, count(distinct m.id) 
from countries c 
cross join age_bins b 
left outer join mytable m on m.country = c.country 
          and m.age between b.min_age and b.max_age 

Si ncecessary vous pouvez simuler les tables comme ceci:

WITH countries as (select distinct country from mytable), 
    age_bins as (select '0-9' age_bin, 0 min_age, 9 max_age from dual 
        union all 
        select '10-19' age_bin, 10 min_age, 19 max_age from dual 
        union all 
        ... 
       ), 
select c.Country, b.age_bin, count(distinct m.id) 
from countries c 
cross join age_bins b 
left outer join mytable m on m.country = c.country 
          and m.age between b.min_age and b.max_age 
+0

ay en tapant la même réponse :) – matja

+0

Merde, exactement l'idée que j'avais. Sauf que j'ai la partie 'count (distinct)' fausse. – Constantin

Questions connexes