web-dev-qa-db-fra.com

SQL - avoir des VS où

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.

176
Adam Sh

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.

318
dasblinkenlight

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.

35
Daniel Mann

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 La clause est exécutée avant - GROUP BY Clause que les enregistrements ne peuvent pas être filtrés en appliquant à un GROUP BY enregistrements appliqués.

"HAVING est identique à la clause WHERE mais est appliqué aux enregistrements groupés".

la clause 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.

21
Pardhu
  1. 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.

  2. WHERE filtre les lignes avant l'agrégation (GROUP BY), tandis que HAVING filtre les groupes après les agrégations.

  3. 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.

Source

13

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.

10
Nhan

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.

8
Akash5288

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.

4
Mihir Trivedi