PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

PostgreSQL - Échec de la sous-requête corrélée ?

Quelques points importants sur l'utilisation de SQL :

  • Vous ne pouvez pas utiliser d'alias de colonne dans la clause WHERE, mais vous le pouvez dans la clause HAVING. C'est la cause de l'erreur que vous avez.
  • Vous pouvez mieux compter avec JOIN et GROUP BY qu'avec 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 me rends compte 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 le WHERE la clause est évaluée sur les lignes, avant GROUP BY réduit les groupes à une seule ligne par groupe. Le HAVING La clause est évaluée après la formation des groupes. Ainsi, vous ne pouvez pas, par exemple, modifier 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 filtres pour les lignes correspondant à une condition, et HAVING filtres pour les groupes qui comptent au moins cinq.

Le point qui cause la confusion chez la plupart des gens, c'est quand ils n'ont pas de GROUP BY clause, donc il semble comme HAVING et WHERE sont interchangeables.

WHERE est évalué avant les expressions dans la liste de sélection. Cela peut ne pas être évident car la syntaxe SQL place la liste de sélection en premier. Ainsi, vous pouvez é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 comme ci-dessus, les expressions de la liste de sélection sont calculées pour chaque ligne , seulement pour rejeter la plupart des résultats à cause du HAVING condition. Cependant, la requête ci-dessous calcule l'expression uniquement pour la ligne unique correspondant à WHERE état.

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érer un ensemble de lignes à partir de table(s), y compris toutes les lignes produites par JOIN .
  2. Évaluer WHERE conditions par rapport à l'ensemble de lignes, en filtrant les lignes qui ne correspondent pas.
  3. Calculer des expressions dans la liste de sélection pour chacune des lignes de l'ensemble.
  4. Appliquez 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. Condenser les groupes en une seule ligne par groupe, selon GROUP BY clause.
  6. Évaluer HAVING conditions par rapport aux groupes, en filtrant les groupes qui ne correspondent pas.
  7. Trier le résultat, selon ORDER BY clause.