Question

J'ai une requête comme celle-ci:

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

Le but est d’obtenir l’id de tous les éléments qui apparaissent 5 fois dans l’autre tableau. Cependant, je reçois cette erreur:

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

Je fais probablement quelque chose de stupide ici, car je suis un peu nouveau dans les bases de données. Y at-il un moyen de résoudre cette requête afin que je puisse accéder à num_things ? Sinon, y a-t-il un autre moyen d'obtenir ce résultat?

Était-ce utile?

La solution

Je pense que vous pourriez simplement réécrire votre requête comme suit:

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

Autres conseils

Quelques points importants sur l'utilisation de SQL:

  • Vous ne pouvez pas utiliser d'alias de colonne dans la clause WHERE, mais dans la clause HAVING. C'est la cause de l'erreur que vous avez.
  • Vous pouvez mieux compter en utilisant JOIN et GROUP BY qu'en utilisant des sous-requêtes corrélées. Ce sera beaucoup plus rapide.
  • Utilisez la clause HAVING pour filtrer les groupes.

Voici comment j'écrirais cette requête:

SELECT t1.id, COUNT(t2.id) AS num_things
FROM t1 JOIN t2 USING (id)
GROUP BY t1.id
HAVING num_things = 5;

Je réalise que cette requête peut ignorer le JOIN avec t1, ??comme dans la solution de Charles Bretana. Mais je suppose que vous voudrez peut-être que la requête inclue d'autres colonnes de t1.

Re: la question dans le commentaire:

La différence est que la clause WHERE est évaluée sur des lignes, avant que GROUP BY ne réduise les groupes que sur une seule ligne. La clause HAVING est évaluée après la formation des groupes. Ainsi, vous ne pouvez pas, par exemple, changer le COUNT () d'un groupe en utilisant HAVING ; vous ne pouvez exclure que le groupe lui-même.

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;

Dans la requête ci-dessus, WHERE filtre pour les lignes correspondant à une condition et HAVING pour les groupes comptant au moins cinq chiffres.

La plupart des gens sont perplexes lorsqu'ils ne possèdent pas de clause GROUP BY , de sorte qu'il semble comme HAVING et < code> WHERE sont interchangeables.

WHERE est évalué avant les expressions de la liste de sélection. Cela n’est peut-être pas évident, car la syntaxe SQL place la liste de sélection en premier. Vous pouvez donc économiser beaucoup de calculs coûteux en utilisant WHERE pour restreindre les lignes.

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

Si vous utilisez une requête semblable à celle ci-dessus, les expressions de la liste de sélection sont calculées pour chaque ligne , uniquement pour écarter la plupart des résultats en raison du HAVING . état. Cependant, la requête ci-dessous calcule l'expression uniquement pour la seule ligne correspondant à la condition WHERE .

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

Donc, pour récapituler, les requêtes sont exécutées par le moteur de base de données selon une série d'étapes:

  1. Génère un ensemble de lignes à partir de table (s), y compris les lignes générées par JOIN .
  2. Évaluez les conditions WHERE par rapport à l'ensemble de lignes, en filtrant les lignes qui ne correspondent pas.
  3. Calculez les expressions dans la liste de sélection pour chacune des lignes.
  4. Appliquer des alias de colonne (notez qu'il s'agit d'une étape distincte, ce qui signifie que vous ne pouvez pas utiliser d'alias dans les expressions de la liste de sélection).
  5. Condensez les groupes sur une seule ligne par groupe, conformément à la clause GROUP BY .
  6. Évaluez les conditions HAVING par rapport aux groupes, en filtrant les groupes qui ne correspondent pas.
  7. Trier le résultat en fonction de la clause ORDER BY .

Toutes les autres suggestions fonctionneraient, mais pour répondre à votre question de base, il suffirait d'écrire

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

Je voudrais mentionner que dans PostgreSQL, il n'y a aucun moyen d'utiliser une colonne avec alias dans une clause.

c'est-à-dire

SELECT usr_id AS my_id FROM utilisateur HAVING my_id = 1

Ne fonctionnera pas.

Un autre exemple qui ne fonctionnera pas:

SELECT su.usr_id AS my_id, COUNT (*) AS val de sys_user AS SU GROUP BY su.usr_id HAVING val > = 1

Il y aura la même erreur: la colonne val n'est pas connue.

Je souligne ceci parce que Bill Karwin a écrit quelque chose qui n’est pas vraiment vrai pour Postgres:

"Vous ne pouvez pas utiliser d'alias de colonne dans la clause WHERE, mais dans la clause HAVING. C’est la cause de l’erreur que vous avez eue. "

essayez ceci

SELECT t1.id,
    (SELECT COUNT(t2.id) as myCount
     FROM t2
     WHERE t2.id = t1.id and myCount=5
          ) as num_things
FROM t1
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top