J'ai les deux tables suivantes:
1. Lecturers (LectID, Fname, Lname, degree).
2. Lecturers_Specialization (LectID, Expertise).
Je veux trouver le conférencier avec le plus de spécialisation. Quand j'essaye ça, ça ne marche pas:
SELECT
L.LectID,
Fname,
Lname
FROM Lecturers L,
Lecturers_Specialization S
WHERE L.LectID = S.LectID
AND COUNT(S.Expertise) >= ALL (SELECT
COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);
Mais quand j'essaye ça, ça marche:
SELECT
L.LectID,
Fname,
Lname
FROM Lecturers L,
Lecturers_Specialization S
WHERE L.LectID = S.LectID
GROUP BY L.LectID,
Fname,
Lname
HAVING COUNT(S.Expertise) >= ALL (SELECT
COUNT(Expertise)
FROM Lecturers_Specialization
GROUP BY LectID);
Quelle est la raison? Merci.
La clause WHERE
introduit une condition sur lignes individuelles; La clause HAVING
introduit une condition sur agrégations, c'est-à-dire les résultats de la sélection dans lesquels un seul résultat, tel que count, average, min, max ou sum, a été produit à partir de multiple rangées. Votre requête appelle un deuxième type de condition (c'est-à-dire une condition sur une agrégation). Par conséquent, HAVING
fonctionne correctement.
En règle générale, utilisez WHERE
avant GROUP BY
et HAVING
après GROUP BY
. C'est une règle plutôt primitive, mais utile dans plus de 90% des cas.
Pendant que vous y êtes, vous voudrez peut-être réécrire votre requête en utilisant la version ANSI de la jointure:
SELECT L.LectID, Fname, Lname
FROM Lecturers L
JOIN Lecturers_Specialization S ON L.LectID=S.LectID
GROUP BY L.LectID, Fname, Lname
HAVING COUNT(S.Expertise)>=ALL
(SELECT COUNT(Expertise) FROM Lecturers_Specialization GROUP BY LectID)
Cela éliminerait WHERE
utilisé comme condition de jointure thêta.
HAVING
fonctionne sur des agrégats. Comme COUNT
est une fonction d'agrégat, vous ne pouvez pas l'utiliser dans une clause WHERE
.
Voici quelques lectures de MSDN sur les fonctions agrégées.
Nous devons d’abord connaître l’ordre d’exécution des clauses, c’est-à-dire FROM> WHERE> GROUP BY> HAVING> DISTINCT> SELECT> ORDER BY. Depuis OÙ La clause est exécutée avant - GROUP BY Clause que les enregistrements ne peuvent pas être filtrés en appliquant OÙ à un GROUP BY enregistrements appliqués.
"HAVING est identique à la clause WHERE mais est appliqué aux enregistrements groupés".
la clause OÙ récupère d'abord les enregistrements en fonction de la condition, puis la clause GROUP BY les regroupe en conséquence, puis la clause HAVING le groupe enregistre en fonction de la condition d’avoir.
La clause WHERE peut être utilisée avec les instructions SELECT, INSERT et UPDATE, alors que HAVING ne peut être utilisée qu'avec une instruction SELECT.
WHERE filtre les lignes avant l'agrégation (GROUP BY), tandis que HAVING filtre les groupes après les agrégations.
La fonction d'agrégat ne peut être utilisée dans la clause WHERE que si elle se trouve dans une sous-requête contenue dans la clause HAVING, alors que les fonctions d'agrégat peuvent être utilisées dans la clause HAVING.
Je n'ai pas vu d'exemple des deux dans une requête. Donc, cet exemple pourrait aider.
/**
INTERNATIONAL_ORDERS - table of orders by company by location by day
companyId, country, city, total, date
**/
SELECT country, city, sum(total) totalCityOrders
FROM INTERNATIONAL_ORDERS with (nolock)
WHERE companyId = 884501253109
GROUP BY country, city
HAVING country = 'MX'
ORDER BY sum(total) DESC
Cela filtre le tableau en premier par companyId, puis le groupe (par pays et par ville) et le filtre en plus pour le regrouper uniquement par ville du Mexique. Le companyId n'était pas nécessaire dans l'agrégation, mais nous avons pu utiliser WHERE pour filtrer uniquement les lignes souhaitées avant d'utiliser GROUP BY.
Vous ne pouvez pas utiliser la clause where avec des fonctions d'agrégat, car fetch doit enregistrer les enregistrements sur la base de la condition. Il est ensuite enregistré, enregistrement par enregistrement, puis extrait l'enregistrement à l'aide de la condition fournie. Donc, cette fois, nous ne pouvons pas savoir où. Alors que la clause fonctionne sur le resultSet que nous obtenons finalement après l'exécution d'une requête.
Exemple de requête:
select empName, sum(Bonus)
from employees
order by empName
having sum(Bonus) > 5000;
Ceci stockera le resultSet dans une mémoire temporaire, puis la clause effectuera son travail. Donc, nous pouvons facilement utiliser les fonctions d'agrégat ici.
1. Nous pouvons utiliser la fonction d'agrégat avec la clause HAVING et non par la clause WHERE, par exemple. min max Moy.
2. La clause WHERE élimine l'enregistrement La clause record Tuple by Tuple HAVING élimine le groupe entier de la collection de groupe
La plupart du temps, HAVING est utilisé lorsque vous avez des groupes de données et WHERE est utilisé lorsque vous avez des données dans des lignes.