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