Quelle est la différence entre AVOIR et OERE?

261

Je dois googler dans le mauvais sens ou je passe un moment stupide dans le temps.

Quelle est la différence entre HAVINGet WHEREdans une SQL SELECTdéclaration?

EDIT: J'ai marqué la réponse de Steven comme étant la bonne, car elle contenait les informations clés sur le lien:

Lorsque GROUP BYn'est pas utilisé, HAVINGse comporte comme une WHEREclause

La situation dans laquelle je l'avais vu WHEREn'avait pas GROUP BYet c'est là que ma confusion a commencé. Bien sûr, tant que vous ne le savez pas, vous ne pouvez pas le spécifier dans la question.

ColinYounger
la source
44
La ligne que vous citez n'est pas du tout l'élément clé. Le bit clé, comme l'a souligné wcm , est qu'il HAVINGs'agit d'un filtre de post-agrégation, alors qu'il WHEREs'agit d'un filtre de pré-agrégation.
Nick Chammas
ce lien m'a aidé à mieux le comprendre que tous les commentaires ci-dessous, pensait que quelqu'un pourrait obtenir de l'aide par ce codeproject.com/Articles/25258/…
Lijin Durairaj

Réponses:

94

HAVING spécifie une condition de recherche pour un groupe ou une fonction d'agrégation utilisée dans l'instruction SELECT.

La source

Steven
la source
369

AYANT: est utilisé pour vérifier les conditions après l'agrégation.
OERE: est utilisé pour vérifier les conditions avant l'agrégation.

Ce code:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City

Vous donne un tableau de toutes les villes de MA et le nombre d'adresses dans chaque ville.

Ce code:

select City, CNT=Count(1)
From Address
Where State = 'MA'
Group By City
Having Count(1)>5

Vous donne un tableau des villes de MA avec plus de 5 adresses et le nombre d'adresses dans chaque ville.

wcm
la source
7
Ce devrait être la réponse acceptée. La distinction entre «avoir» et «où» le montre immédiatement.
Paul
27

La différence numéro un pour moi: si elle HAVINGétait supprimée du langage SQL, la vie continuerait plus ou moins comme avant. Certes, une requête minoritaire devrait être réécrite à l'aide d'une table dérivée, CTE, etc., mais il serait sans doute plus facile à comprendre et à maintenir en conséquence. Peut-être que le code d'optimisation des fournisseurs devrait être réécrit pour en tenir compte, encore une fois une opportunité d'amélioration au sein de l'industrie.

Considérons maintenant un instant la suppression WHEREde la langue. Cette fois, la majorité des requêtes existantes devraient être réécrites sans construction alternative évidente. Les codeurs devraient faire preuve de créativité, par exemple une jointure interne à une table connue pour contenir exactement une ligne (par exemple DUALdans Oracle) en utilisant la ONclause pour simuler la WHEREclause précédente . De telles constructions seraient artificielles; il serait évident qu'il manquait quelque chose dans la langue et la situation serait pire en conséquence.

TL; DR nous pourrions perdre HAVINGdemain et les choses ne seraient pas pires, peut-être mieux, mais on ne peut pas en dire autant WHERE.


D'après les réponses ici, il semble que beaucoup de gens ne réalisent pas qu'une HAVINGclause peut être utilisée sans GROUP BYclause. Dans ce cas, la HAVINGclause est appliquée à l'expression de table entière et requiert que seules les constantes apparaissent dans la SELECTclause. En règle générale, la HAVINGclause impliquera des agrégats.

C'est plus utile qu'il n'y paraît. Par exemple, considérez cette requête pour tester si la namecolonne est unique pour toutes les valeurs dans T:

SELECT 1 AS result
  FROM T
HAVING COUNT( DISTINCT name ) = COUNT( name );

Il n'y a que deux résultats possibles: si la HAVINGclause est vraie, le résultat sera une seule ligne contenant la valeur 1, sinon le résultat sera l'ensemble vide.

un jour
la source
Est-ce que cela équivaudrait à "SELECT COUNT (DISTINCT name) = COUNT (name) FROM T"?
MSpreij
@MSpreij Je ne sais pas si cela fonctionne pour vous, mais cela ne fonctionne pas sur SQL Server 2005 mais le premier le fait
Joe
22

La clause HAVING a été ajoutée à SQL car le mot clé WHERE n'a pas pu être utilisé avec des fonctions d'agrégation.

Consultez ce lien w3schools pour plus d'informations

Syntaxe:

SELECT column_name, aggregate_function(column_name)
FROM table_name
WHERE column_name operator value
GROUP BY column_name
HAVING aggregate_function(column_name) operator value

Une requête comme celle-ci:

SELECT column_name, COUNT( column_name ) AS column_name_tally
  FROM table_name
 WHERE column_name < 3
 GROUP 
    BY column_name
HAVING COUNT( column_name ) >= 3;

... peut être réécrit en utilisant une table dérivée (et en omettant HAVING) comme ceci:

SELECT column_name, column_name_tally
  FROM (
        SELECT column_name, COUNT(column_name) AS column_name_tally
          FROM table_name
         WHERE column_name < 3
         GROUP 
            BY column_name
       ) pointless_range_variable_required_here
 WHERE column_name_tally >= 3;
Kaiser Advisor
la source
3
Vous avez un peu manqué le point: a HAVINGété ajouté parce que les tables dérivées n'avaient pas été ajoutées au langage et jusqu'à ce qu'elles soient SQL n'était pas complètement complète et une fois qu'elles étaient inévitablement HAVINGdevenues redondantes.
onedaywhen
21

La différence entre les deux réside dans la relation avec la clause GROUP BY:

  • O comes vient avant GROUP BY; SQL évalue la clause WHERE avant de regrouper les enregistrements.

  • AYANT vient après GROUP BY; SQL évalue HAVING après avoir regroupé les enregistrements.

sélectionner le diagramme d'instruction

Références

Paul Sweatte
la source
Étant donné que GROUP BY et HAVING sont tous deux facultatifs, le diagramme montre les deux cas, suivez simplement les flèches.
Paul Sweatte
Exemple de requête de ma réponse à cette question: SELECT 1 AS result FROM T HAVING...- dans votre diagramme, je ne peux pas accéder HAVINGsans passer par GROUP BYmais ma requête parfaitement valide et utile n'a pas GROUP BY. Point mineur: vous n'avez pas la possibilité d'inclure des valeurs littérales dans la SELECTclause.
onedaywhen
@onedaywhen Puisque vous connaissez le GROUP BY implicite, pourquoi ne l'avez-vous pas mentionné? Savez-vous si ce comportement correspond à ce que vous attendez ou non?
Paul Sweatte du
Il me semble que vous me citez hors contexte. La question portait sur l'écart apparent de mySQL par rapport à la norme, tout sauf le dernier paragraphe de ma réponse décrit le comportement de la norme, et le dernier fait allusion à «la clause GROUP BY implicite mentionnée dans d'autres réponses ». Êtes-vous en train de dire que votre diagramme est destiné à décrire (tous) les comportements implicites? Ne serait-il pas plus utile de s'en tenir uniquement au code dont vous avez besoin pour obtenir le comportement souhaité?
onedaywhen
... Je ne sais pas à quel comportement vous faites allusion dans le deuxième lien. Le résultat souhaité est que vous corrigez le diagramme pour afficher le chemin valide (explicite) que j'ai mentionné. Pensez-y: le diagramme couvre une requête entière mais la question ne s'intéresse qu'à la WHERE->HAVINGpartie, donc je pense qu'il mérite une attention particulière aux détails. Si vous pensez que ma réponse est fausse, modifiez-la ou postez une correction suggérée dans les commentaires.
onedaywhen
12

HAVINGest utilisé lorsque vous utilisez un agrégat tel que GROUP BY.

SELECT edc_country, COUNT(*)
FROM Ed_Centers
GROUP BY edc_country
HAVING COUNT(*) > 1
ORDER BY edc_country;
Galvanais
la source
8

WHERE est appliqué comme une limitation sur l'ensemble renvoyé par SQL; il utilise les index et les fonctions d'ensembles intégrés de SQL et est donc le moyen le plus rapide de filtrer les ensembles de résultats. Utilisez toujours OERE autant que possible.

AVOIR est nécessaire pour certains filtres d'agrégats. Il filtre la requête APRÈS sql a récupéré, assemblé et trié les résultats. Par conséquent, il est beaucoup plus lent que OERE et doit être évité, sauf dans les situations qui l'exigent.

SQL Server vous permettra de vous débarrasser de l'utilisation de HAVING même lorsque WHERE serait beaucoup plus rapide. Ne le fais pas.

davidcl
la source
La prise en charge des tables dérivées dans le langage SQL signifie que votre affirmation "HAVING est nécessaire pour certains filtres d'agrégation" est fausse.
onedaywhen
1
C'est un bon point. Au cours des trois années écoulées depuis que j'ai écrit cette réponse, j'ai certainement migré vers l'utilisation de tableaux dérivés où j'aurais auparavant utilisé HAVING. Je n'ai pas réfléchi à la question de savoir si HAVING a encore des cas d'utilisation qui ont du sens. Je ne sais pas non plus si une table dérivée fonctionnera universellement mieux que HAVING.
davidcl
7

La clause WHERE ne fonctionne pas pour les fonctions d'agrégation
signifie: vous ne devez pas utiliser comme ce bonus: nom de table

SELECT name  
FROM bonus  
GROUP BY name  
WHERE sum(salary) > 200  

ICI Au lieu d'utiliser la clause WHERE, vous devez utiliser HAVING ..

sans utiliser la clause GROUP BY, la clause HAVING fonctionne comme la clause WHERE

SELECT name  
FROM bonus  
GROUP BY name  
HAVING sum(salary) > 200  
Achilles Ram Nakirekanti
la source
4

Différence n / b WHEREet HAVINGclause:

La principale différence entre WHEREet la HAVINGclause est, WHEREest utilisée pour les opérations de ligne et HAVINGest utilisée pour les opérations de colonne.

Pourquoi avons-nous besoin d'une HAVINGclause?

Comme nous le savons, les fonctions d'agrégation ne peuvent être exécutées que sur des colonnes, nous ne pouvons donc pas utiliser de fonctions d'agrégation dans la WHEREclause. Par conséquent, nous utilisons des fonctions d'agrégation dans la HAVINGclause.

M Asad Ali
la source
2

Lorsque GROUP BYn'est pas utilisé, les clauses WHEREet HAVINGsont essentiellement équivalentes.

Cependant, quand GROUP BYest utilisé:

  • La WHEREclause est utilisée pour filtrer les enregistrements d'un résultat. Le filtrage se produit avant tout regroupement.
  • La HAVINGclause est utilisée pour filtrer les valeurs d'un groupe (c'est-à-dire pour vérifier les conditions une fois l'agrégation en groupes effectuée).

Ressource d' ici

bebosh
la source
avoir et où ne sont pas essentiellement équivalents. cela donnera une erreur lors de l'exécution. n'est pas valide dans la clause HAVING car il n'est contenu ni dans une fonction d'agrégation ni dans la clause GROUP BY.
Nagendra Kumar
2

Une façon de penser est que la clause having est un filtre supplémentaire à la clause where.

Une clause WHERE est utilisée pour filtrer les enregistrements d'un résultat. Le filtre se produit avant tout regroupement. Une clause HAVING est utilisée pour filtrer les valeurs d'un groupe

Ved Prakash
la source
1

Dans une requête d'agrégation, (toute requête dans laquelle une fonction d'agrégation est utilisée) les prédicats d'une clause where sont évalués avant la génération de l'ensemble de résultats intermédiaires agrégés,

Les prédicats d'une clause having sont appliqués au jeu de résultats agrégé APRÈS sa génération. C'est pourquoi les conditions de prédicat sur les valeurs agrégées doivent être placées dans la clause Have, pas dans la clause Where, et pourquoi vous pouvez utiliser des alias définis dans la clause Select dans une clause Have, mais pas dans une clause Where.

Charles Bretana
la source
1

J'ai eu un problème et j'ai découvert une autre différence entre WHEREet HAVING. Il n'agit pas de la même manière sur les colonnes indexées.

WHERE my_indexed_row = 123 affichera les lignes et effectuera automatiquement un "ORDER ASC" sur les autres lignes indexées.

HAVING my_indexed_row = 123 affiche tout, de la plus ancienne ligne "insérée" à la plus récente, sans ordre.

Simmoniz
la source
Comment savez-vous qu'il s'agit d'une différence définie entre les deux, plutôt que d'un accident de mise en œuvre du serveur SQL particulier que vous utilisiez?
JdeBP
Je viens de le tester sur MariaDB. Je suppose que c'est le serveur SQL que j'utilisais il y a 8 ans qui a produit des résultats différents.
Simmoniz
0

D' ici .

la norme SQL exige que HAVING ne fasse référence qu'aux colonnes de la clause GROUP BY ou aux colonnes utilisées dans les fonctions d'agrégation

par opposition à la clause WHERE qui est appliquée aux lignes de la base de données

Harry Lime
la source
La source dit: «L'utilisation des positions de colonne est déconseillée car la syntaxe a été supprimée de la norme SQL». Malheureusement, c'est faux: rien n'est jamais supprimé de la norme, ce qui est ironiquement la raison pour laquelle nous avons encore des HAVINGdécennies après qu'il a été «déprécié» par les tableaux dérivés.
jour,
Légèrement pédant mais la citation n'est pas correcte, par exemple, considérez SELECT 1 FROM T HAVING COUNT(*) >= 1;- ne référence pas les colonnes dans la GROUP BYclause (il n'y en a pas) ni les colonnes dans les fonctions d'agrégation (la requête ne fait référence à aucune colonne).
jour,
0

Tout en travaillant sur un projet, c'était aussi ma question. Comme indiqué ci-dessus, le HAVING vérifie la condition sur le résultat de la requête déjà trouvé. Mais OERE est pour vérifier la condition pendant l'exécution de la requête.

Permettez-moi de donner un exemple pour illustrer cela. Supposons que vous ayez une table de base de données comme celle-ci.

utilisable {int userid, date datefield, int dailyincome}

Supposons que les lignes suivantes soient dans le tableau:

1, 2011-05-20, 100

1, 2011-05-21, 50

1, 2011-05-30, 10

2, 2011-05-30, 10

2, 2011-05-20, 20

Maintenant, nous voulons obtenir le userids et sum(dailyincome)dontsum(dailyincome)>100

Si nous écrivons:

SELECT userid, sum (dailyincome) FROM utilisable WHERE sum (dailyincome)> 100 GROUP BY userid

Ce sera une erreur. La bonne requête serait:

SELECT userid, sum (dailyincome) FROM usertable GROUP BY userid AAVANT sum (dailyincome)> 100

Nayan
la source
0

La clause WHERE est utilisée pour comparer les valeurs de la table de base, tandis que la clause HAVING peut être utilisée pour filtrer les résultats des fonctions d'agrégation dans le jeu de résultats de la requête Cliquez ici !

Muhammad Ali
la source
0

Lorsque GROUP BY n'est pas utilisé, les clauses WHERE et HAVING sont essentiellement équivalentes.

Cependant, lorsque GROUP BY est utilisé:

  • La clause WHERE est utilisée pour filtrer les enregistrements d'un résultat. Le filtrage se produit avant tout regroupement.
  • La clause HAVING est utilisée pour filtrer les valeurs d'un groupe (c'est-à-dire pour vérifier les conditions une fois l'agrégation en groupes effectuée).
rjose
la source
-1

J'utilise HAVING pour contraindre une requête basée sur les résultats d'une fonction d'agrégation. EG select * in blahblahblah group by SOMETHING having count (SOMETHING)> 0

JasonTrue
la source
-1

Il se peut que le sujet du "où" soit une ligne, tandis que le sujet du "avoir" soit un groupe. Ai-je raison?

Viky Leaf
la source
3
Vous devez être sûr avant de poster une réponse. Cela pourrait induire les autres en erreur.
pippin1289