Quelques points importants sur l'utilisation de SQL:
- Vous ne pouvez pas utiliser les alias de colonne dans la clause WHERE, mais vous pouvez en la clause HAVING. C'est la cause de l'erreur que tu as eue.
- Vous pouvez mieux faire votre compte 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.
est ici la façon dont j'écris 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 cette requête peut ignorer l'JOIN
avec t1, comme dans la solution de Charles Bretana. Mais je suppose que vous pourriez vouloir 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 rangées, avant GROUP BY
réduit les groupes à une seule rangée par groupe. La clause HAVING
est évaluée après la formation des groupes. Vous ne pouvez donc 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 demande de recherche ci-dessus, WHERE
filtres pour les lignes correspondant à une condition, et HAVING
filtres pour les groupes qui ont au moins cinq comptage.
Le point qui provoque la plupart des gens est la confusion quand ils n'ont pas une clause GROUP BY
, 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. 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 comme celle-ci, les expressions dans la liste de sélection sont calculés pour chaque ligne , pour jeter la plupart des résultats en raison de la condition HAVING
.Toutefois, la requête ci-dessous calcule l'expression uniquement pour la ligne correspondant à la condition WHERE
.
SELECT <expensive expressions>
FROM t1
WHERE primaryKey = 1234;
Donc, pour résumer, les requêtes sont dirigées par le moteur de base de données selon la série d'étapes:
- Générer ensemble de lignes de la table (s), y compris toutes les lignes produites par
JOIN
.
- Évaluez les conditions
WHERE
par rapport à l'ensemble des lignes, en filtrant les lignes qui ne correspondent pas.
- Calculer des expressions dans select-list pour chacune des lignes.
- 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 à une seule ligne par groupe, selon la clause
GROUP BY
.
- Évaluez les conditions
HAVING
par rapport aux groupes, en filtrant les groupes qui ne correspondent pas.
- Trier le résultat, conformément à la clause
ORDER BY
.
Oh, j'aurais dû relire le but. Tu as raison. Au début, j'étais comme, "mais alors vous perdez les informations de compte, et si vous en avez besoin?" – Kev
oui, cela fonctionne. étrange, je pensais que j'ai essayé cela au début, mais a obtenu un «pas d'agrégats autorisés dans where clause» ou quelque chose. J'ai dû faire quelque chose de différent. Y at-il une raison pour laquelle la façon dont j'ai posté ne fonctionne pas, cependant? – Claudiu
Je ne peux pas le trouver, mais il y avait un fil dans les newsgroups à ce sujet, et il y avait une raison. Tout ce dont je me souviens, c'est que quelqu'un a dit que (si vous avez répété la fonction), dans la plupart des cas, le temps de calcul deux fois est vraiment minime. – Kev