FILTERCláusula agregada no Postgres 9.4+
Desde o Postgres 9.4, existe uma maneira limpa e rápida (padrão 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;
totalacrescenta-se low, mide high, a não ser nulo ou outros valores estão envolvidos.
Ligações:
Leia também abaixo.
Postgres 9.3-
Existem algumas técnicas:
A @Phil forneceu uma CASEdeclaração da maneira padrão (exceto sum(1), que não é a maneira padrão). Eu gosto de usar um formulário mais curto:
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;
Se seus valores forem os definidos na sua pergunta (apenas 0- 10possível), simplifique ainda mais:
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;
Um pouco mais curto, um pouco mais rápido.
Diferenças sutis
Há diferenças sutis quando comparado com sum()a resposta de Phil :
Mais importante, por documentação :
Deve-se observar que, exceto por count, essas funções retornam um valor nulo quando nenhuma linha é selecionada. Em particular, sumsem linhas retorna nulo, não zero, como se poderia esperar, ...
count(*) é o caminho padrão e um pouco mais rápido que sum(1). Novamente, nulo vs. 0 se aplica.
Qualquer uma dessas consultas (incluindo as de Phil) conta valores nulos para total. Se isso não for desejável, use:
count(score) AS total_not_null
SQL Fiddle na página 9.3.
db <> mexa aqui na página 10.