Pergunta

Eu tenho uma consulta como esta:

SELECT t1.id,
    (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) as num_things
FROM t1
WHERE num_things = 5;

O objetivo é obter o ID de todos os elementos que aparecem 5 vezes na outra tabela. No entanto, eu recebo este erro:

ERROR: column "num_things" does not exist
SQL state: 42703

Provavelmente estou fazendo algo bobo aqui, como eu sou um pouco novo para bancos de dados. Existe uma maneira de corrigir essa consulta para que eu possa acessar num_things? Ou, se não, existe alguma outra maneira de alcançar este resultado?

Foi útil?

Solução

Eu acho que você poderia simplesmente reescrever sua consulta assim:

SELECT t1.id
FROM t1
WHERE (SELECT COUNT(t2.id)
     FROM t2
     WHERE t2.id = t1.id
          ) = 5;

Outras dicas

Alguns pontos importantes sobre como usar SQL:

  • Você não pode usar apelidos de coluna na cláusula WHERE, mas você pode na cláusula HAVING. Essa é a causa do erro que você tem.
  • Você pode fazer a sua contagem de melhor utilizar um JOIN e GROUP BY que usando subconsultas correlacionados. Vai ser muito mais rápido.
  • Use a cláusula HAVING para grupos de filtros.

Esta é a maneira que eu ia escrever 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;

Eu percebo esta consulta pode ignorar a JOIN com t1, como na solução de Charles Bretana. Mas eu suponho que você pode querer a consulta para incluir algumas outras colunas de T1.


Re: a pergunta no comentário:

A diferença é que a cláusula WHERE é avaliada em linhas, antes GROUP BY reduz grupos para uma única linha por grupo. A cláusula HAVING é avaliada depois os grupos são formados. Então você não pode, por exemplo, mudar 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, filtros WHERE para linhas correspondentes uma condição e filtros HAVING para grupos que têm pelo menos cinco contagem.

O ponto que faz com que a maioria das pessoas confusão é quando eles não têm uma cláusula GROUP BY, por isso parece como HAVING e WHERE são intercambiáveis.

WHERE é avaliada antes expressões na lista de seleção. Isto pode não ser óbvio, porque coloca sintaxe SQL do select-lista em primeiro lugar. Então você pode salvar um monte de computação caro usando WHERE para restringir linhas.

SELECT <expensive expressions>
FROM t1
HAVING primaryKey = 1234;

Se você usar uma consulta como o acima, as expressões na lista de seleção são computados para cada linha , apenas para descartar a maioria dos resultados por causa da condição HAVING. No entanto, a consulta abaixo calcula a expressão apenas para o única linha combinando a condição WHERE.

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 a série de etapas:

  1. Gerar conjunto de linhas da tabela (s), incluindo todas as linhas produzidas pela JOIN.
  2. Avaliar as condições WHERE contra o conjunto de linhas, filtrando as linhas que não correspondem.
  3. expressões de computação em select-list para cada no conjunto de linhas.
  4. Aplicar aliases de coluna (note que este é um passo separado, o que significa que você não pode usar aliases em expressões na lista de seleção).
  5. grupos condense em uma única linha por grupo, de acordo com a cláusula GROUP BY.
  6. Avaliar as condições HAVING contra grupos, filtrando grupos que não correspondem.
  7. Classificar resultar, de acordo com a cláusula ORDER BY.

Todas as outras sugestões iria funcionar, mas para responder à sua pergunta básica que seria suficiente para gravação

  SELECT id  From T2
  Group By Id
  Having Count(*) = 5

Eu gostaria de mencionar que no PostgreSQL não há nenhuma maneira de usar coluna alias na cláusula having.

i.

SELECIONAR usr_id AS my_id DE usuário ter my_id = 1

não vai funcionar.

Outro exemplo que não está indo para o trabalho:

SELECIONAR su.usr_id AS my_id, COUNT (*) AS val DE sys_user AS su GROUP BY su.usr_id TENDO val> = 1

Não será o mesmo erro:. Coluna val não é conhecida

Im highliting isso porque Bill Karwin escreveu alguma coisa não é realmente verdadeiro para Postgres:

"Você não pode usar apelidos de coluna na cláusula WHERE, mas você pode na cláusula HAVING. Essa é a causa do erro que você tem."

Tente este

SELECT t1.id,
    (SELECT COUNT(t2.id) as myCount
     FROM t2
     WHERE t2.id = t1.id and myCount=5
          ) as num_things
FROM t1
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top