FILTERClause d' agrégation 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;
totaladditionne low, midet high, à moins que d' autres valeurs NULL ou sont impliquées.
Liens:
Lisez également ci-dessous.
Postgres 9.3-
Il existe quelques techniques:
@Phil a fourni la méthode standard avec une CASEinstruction (à 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 (uniquement 0- 10possible), 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.
Différences subtiles
Il y a de subtiles différences par rapport à sum()dans la 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, sumaucune ligne ne renvoie null, pas zéro comme on pourrait s'y attendre, ...
count(*) est 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.