J'ai une table de base de données Postgres foo
qui, entre autres choses, a une colonne pour score
qui va de 0 à 10. Je veux qu'une requête renvoie le nombre total de scores, le nombre de scores entre 0 et 3, le nombre de scores entre 4 et 6 et le nombre de scores entre 7 et 10. Quelque chose comme ceci:
SELECT
COUNT(*) as total,
COUNT(
SELECT * from foo where score between 0 and 3;
) as low,
COUNT(
SELECT * from foo where score between 4 and 6;
) as mid,
COUNT(
SELECT * from foo where score between 7 and 10;
) as high
FROM foo;
J'ai essayé cela, mais j'ai eu une erreur avec les SELECT
dans les instructions COUNT
. Des idées comment je peux faire ça? Je suis sûr qu'il y a un moyen super simple dans Postgres. Je n'arrive pas à trouver les termes corrects pour Google.
Utilisez simplement les instructions conditionnelles SUM()
par colonne pour chaque plage de nombres. Le total peut être additionné en utilisant simplement SUM(1)
, en supposant que toutes les données du tableau se trouvent dans une des plages - sinon, restreignez-la comme avec les autres.
select sum(case when score between 0 and 3 then 1 else 0 end) as minrange,
sum(case when score between 4 and 6 then 1 else 0 end) as midrange,
sum(case when score between 7 and 10 then 1 else 0 end) as maxrange,
sum(1) as total
from foo;
FILTER
dans Postgres 9.4+Depuis Postgres 9.4, il existe une méthode propre et rapide (standard SQL):
SELECT count(*) FILTER (WHERE score BETWEEN 0 AND 3) AS low
, count(*) FILTER (WHERE score BETWEEN 4 AND 7) AS mid
, count(*) FILTER (WHERE score BETWEEN 8 AND 10) AS high
, count(*) AS total
FROM foo;
total
additionne low
, mid
et high
, sauf si NULL ou d'autres valeurs sont impliquées.
Liens:
Lisez également ci-dessous.
Il existe quelques techniques:
@ Phil a fourni la méthode standard avec une instruction CASE
(à l'exception de sum(1)
, qui n'est pas la méthode standard). J'aime utiliser un formulaire plus court:
SELECT count(score BETWEEN 0 AND 3 OR NULL) AS low
, count(score BETWEEN 4 AND 6 OR NULL) AS mid
, count(score BETWEEN 7 AND 10 OR NULL) AS high
, count(*) AS total
FROM foo;
Si vos valeurs sont telles que définies dans votre question (seulement 0
- 10
Possible), simplifiez davantage:
SELECT count(score < 4 OR NULL) AS low
, count(score BETWEEN 4 AND 6 OR NULL) AS mid
, count(score > 6 OR NULL) AS high
, count(*) AS total
FROM foo;
Un peu plus court, à peine plus rapide.
Il y a des différences subtiles par rapport à sum()
dans Réponse de Phil :
Plus important encore, par documentation :
Il convient de noter qu'à l'exception de
count
, ces fonctions renvoient une valeur nulle lorsqu'aucune ligne n'est sélectionnée. En particulier,sum
sans ligne retourne null, pas zéro comme on pourrait s'y attendre, ...
count(*)
is la manière standard et un peu plus rapide que sum(1)
. Encore une fois, null vs 0 s'applique.
L'une ou l'autre de ces requêtes (y compris celle de Phil) compte des valeurs nulles pour total
. Si ce n'est pas souhaitable, utilisez plutôt:
count(score) AS total_not_null
SQL Fiddle en pg 9.3.
db <> violon ici en pg 10.