FILTERCláusula agregada en Postgres 9.4+
Desde Postgres 9.4 hay una manera limpia y rápida (estándar 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;
totalse suma low, midy high, a no ser nulo o demás valores están involucrados.
Enlaces:
Lea también a continuación.
Postgres 9.3-
Hay un par de técnicas:
@Phil proporcionó la forma estándar con una CASEdeclaración (excepto sum(1), que no es la forma estándar). Me gusta usar una forma más corta:
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 sus valores son como se definen en su pregunta (sólo 0- 10es posible), simplificar aún más:
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 poco más corto, apenas más rápido.
Diferencias sutiles
Hay sutiles diferencias cuando se compara con sum()en la respuesta de Phil :
Lo más importante, por documentación :
Cabe señalar que, a excepción de count, estas funciones devuelven un valor nulo cuando no se seleccionan filas. En particular, sumde ninguna fila devuelve nulo, no cero como cabría esperar ...
count(*) es la forma estándar y un poco más rápido que sum(1). De nuevo, se aplica nulo vs. 0.
Cualquiera de estas consultas (incluidas las de Phil) cuenta valores nulos para total. Si eso no es deseable, use en su lugar:
count(score) AS total_not_null
SQL Fiddle en la página 9.3.
db <> violín aquí en la página 10.