PostgreSQL
 sql >> Base de Dados >  >> RDS >> PostgreSQL

PostgreSQL - Falha na subconsulta correlacionada?


Alguns pontos importantes sobre o uso do SQL:
  • Você não pode usar aliases de coluna na cláusula WHERE, mas pode usar na cláusula HAVING. Essa é a causa do erro que você recebeu.
  • Você pode fazer sua contagem melhor usando um JOIN e GROUP BY do que usando subconsultas correlacionadas. Será muito mais rápido.
  • Use a cláusula HAVING para filtrar grupos.

Aqui está a maneira como eu escreveria esta consulta:
SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Percebo que esta consulta pode pular o JOIN com t1, como na solução de Charles Bretana. Mas suponho que você queira que a consulta inclua algumas outras colunas de t1.

Re:a pergunta no comentário:

A diferença é que o WHERE cláusula é avaliada em linhas, antes de GROUP BY reduz grupos para uma única linha por grupo. O HAVING cláusula é avaliada após a formação dos grupos. Então você não pode, por exemplo, alterar o COUNT() de um grupo usando HAVING; você só pode excluir o próprio grupo.
SELECT t1.id, COUNT(t2.id) as num
FROM t1 JOIN t2 USING (id)
WHERE t2.attribute = <value>
GROUP BY t1.id
HAVING num > 5;

Na consulta acima, WHERE filtros para linhas que correspondem a uma condição e HAVING filtros para grupos que têm pelo menos cinco contagem.

O ponto que causa confusão na maioria das pessoas é quando elas não têm um GROUP BY cláusula, então parece como HAVING e WHERE são intercambiáveis.

WHERE é avaliado antes de expressões na lista de seleção. Isso pode não ser óbvio porque a sintaxe SQL coloca a lista de seleção em primeiro lugar. Assim, você pode economizar muito cálculo caro usando WHERE para restringir as linhas.
SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Se você usar uma consulta como a acima, as expressões na lista de seleção serão calculadas para cada linha , apenas para descartar a maioria dos resultados devido ao HAVING doença. No entanto, a consulta abaixo calcula a expressão apenas para a linha única correspondendo a WHERE doença.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;

Então, para recapitular, as consultas são executadas pelo mecanismo de banco de dados de acordo com uma série de etapas:
  1. Gerar conjunto de linhas da(s) tabela(s), incluindo todas as linhas produzidas por JOIN .
  2. Avalie WHERE condições contra o conjunto de linhas, filtrando as linhas que não correspondem.
  3. Cálculo de expressões na lista de seleção para cada um no conjunto de linhas.
  4. Aplicar aliases de coluna (observe que esta é uma etapa separada, o que significa que você não pode usar aliases em expressões na lista de seleção).
  5. Condense os grupos em uma única linha por grupo, de acordo com GROUP BY cláusula.
  6. Avalie HAVING condições contra grupos, filtrando grupos que não correspondem.
  7. Ordenar resultado, de acordo com ORDER BY cláusula.