Was ist der Unterschied zwischen HAVING und WHERE?


260

Ich muss falsch googeln oder ich habe einen dummen Moment in der Zeit.

Was ist der Unterschied zwischen HAVINGund WHEREin einer SQL SELECTAussage?

EDIT: Ich habe Stevens Antwort als die richtige markiert, da sie die wichtigsten Informationen auf dem Link enthielt:

Wenn GROUP BYnicht verwendet, HAVINGverhält es sich wie eine WHEREKlausel

Die Situation, die ich gesehen hatte, WHEREhatte nicht GROUP BYund hier begann meine Verwirrung. Bis Sie dies wissen, können Sie es natürlich nicht in der Frage angeben.


43
Die Zeile, die Sie zitieren, ist überhaupt nicht das Schlüsselbit. Wie wcm hervorhob , ist das Schlüsselbit ein NachaggregationsfilterHAVING , während WHEREes sich um einen Voraggregationsfilter handelt .
Nick Chammas

Dieser Link hat mir geholfen, es besser zu verstehen als alle Kommentare unten, dachte, jemand könnte Hilfe von diesem codeproject.com/Articles/25258/…
Lijin Durairaj

Antworten:


93

HAVING gibt eine Suchbedingung für eine Gruppe oder eine Aggregatfunktion an, die in der SELECT-Anweisung verwendet wird.

Quelle


368

HAVING: wird verwendet, um die Bedingungen nach der Aggregation zu überprüfen .
WO: wird verwendet, um die Bedingungen zu überprüfen, bevor die Aggregation stattfindet.

Dieser Code:

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

Gibt Ihnen eine Tabelle aller Städte in MA und die Anzahl der Adressen in jeder Stadt.

Dieser Code:

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

Gibt Ihnen eine Tabelle mit Städten in MA mit mehr als 5 Adressen und der Anzahl der Adressen in jeder Stadt.


7
Dies sollte die akzeptierte Antwort sein. Die Unterscheidung zwischen "haben" und "wo" macht dies sofort deutlich.
Paul

27

Der größte Unterschied für mich: Wenn HAVINGer aus der SQL-Sprache entfernt würde, würde das Leben mehr oder weniger so weitergehen wie zuvor. Sicherlich müssten Minderheitsabfragen unter Verwendung einer abgeleiteten Tabelle, eines CTE usw. neu geschrieben werden, aber sie wären wahrscheinlich leichter zu verstehen und zu pflegen. Möglicherweise müsste der Optimierungscode der Anbieter neu geschrieben werden, um dies zu berücksichtigen. Dies ist wiederum eine Gelegenheit zur Verbesserung innerhalb der Branche.

Betrachten Sie nun für einen Moment das Entfernen WHEREaus der Sprache. Diesmal müsste die Mehrzahl der vorhandenen Abfragen ohne ein offensichtliches alternatives Konstrukt neu geschrieben werden. Codierer müssten kreativ werden, z. B. innerer Join zu einer Tabelle, von der bekannt ist, dass sie genau eine Zeile enthält (z. B. DUALin Oracle), indem sie die ONKlausel verwenden, um die vorherige WHEREKlausel zu simulieren . Solche Konstruktionen würden erfunden; Es wäre offensichtlich, dass etwas in der Sprache fehlte und die Situation sich dadurch verschlechtern würde.

TL; DR könnten wir HAVINGmorgen verlieren und die Dinge wären nicht schlechter, möglicherweise besser, aber das Gleiche kann man nicht sagen WHERE.


Aus den Antworten hier geht hervor, dass viele Leute nicht erkennen, dass eine HAVINGKlausel ohne GROUP BYKlausel verwendet werden kann. In diesem Fall wird die HAVINGKlausel auf den gesamten Tabellenausdruck angewendet und erfordert, dass nur Konstanten in der SELECTKlausel erscheinen. In der Regel umfasst die HAVINGKlausel Aggregate.

Dies ist nützlicher als es klingt. Betrachten Sie diese Abfrage beispielsweise, um zu testen, ob die nameSpalte für alle Werte in T: eindeutig ist.

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

Es gibt nur zwei mögliche Ergebnisse: Wenn die HAVINGKlausel wahr ist, ist das Ergebnis eine einzelne Zeile, die den Wert enthält 1, andernfalls ist das Ergebnis die leere Menge.


Wäre das gleichbedeutend mit "SELECT COUNT (DISTINCT Name) = COUNT (Name) FROM T"?
MSpreij

@MSpreij Weiß nicht, ob das für Sie funktioniert, aber es funktioniert nicht auf SQL Server 2005, aber der erste funktioniert
Joe

22

Die HAVING-Klausel wurde zu SQL hinzugefügt, da das Schlüsselwort WHERE nicht mit Aggregatfunktionen verwendet werden konnte.

Weitere Informationen finden Sie unter diesem Link zu w3schools

Syntax:

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

Eine Abfrage wie diese:

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;

... kann unter Verwendung einer abgeleiteten Tabelle (und Weglassen der HAVING) wie folgt umgeschrieben werden :

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;

3
Sie haben den Punkt etwas übersehen: HAVINGwurde hinzugefügt, weil abgeleitete Tabellen nicht zur Sprache hinzugefügt wurden und bis sie SQL waren, nicht relational vollständig waren und sobald sie unvermeidlich HAVINGüberflüssig wurden.
Tag, wenn

21

Der Unterschied zwischen den beiden liegt in der Beziehung zur GROUP BY-Klausel:

  • WO kommt vor GROUP BY; SQL wertet die WHERE-Klausel aus, bevor Datensätze gruppiert werden.

  • HAVING kommt nach GROUP BY; SQL wertet HAVING aus, nachdem Datensätze gruppiert wurden.

Anweisungsdiagramm auswählen

Verweise


Da GROUP BY und HAVING beide optional sind, zeigt das Diagramm beide Fälle. Folgen Sie einfach den Pfeilen.
Paul Sweatte

Beispielabfrage aus meiner Antwort auf diese Frage: SELECT 1 AS result FROM T HAVING...- In Ihrem Diagramm komme ich nicht durch, HAVINGohne durchzugehen, GROUP BYaber meine vollkommen gültige und nützliche Abfrage hat keine GROUP BY. Kleiner Punkt: Sie haben nicht die Möglichkeit, Literalwerte in die SELECTKlausel aufzunehmen.
Tag, wenn

@onedaywhen Da Sie über die implizite GROUP BY Bescheid wissen , warum haben Sie sie nicht erwähnt? Wissen Sie, ob Sie dieses Verhalten erwarten oder nicht?
Paul Sweatte

Ich denke, Sie zitieren mich aus dem Zusammenhang. Die Frage betraf die offensichtliche Abweichung von mySQL vom Standard, alle bis auf den letzten Absatz meiner Antwort beschreiben das Standardverhalten und der letzte spielt auf "die implizite GROUP BY-Klausel an, die in anderen Antworten erwähnt wird ". Wollen Sie damit sagen, dass Ihr Diagramm (alle) impliziten Verhaltensweisen beschreiben soll? Wäre es nicht sinnvoller, sich nur an den Code zu halten, den Sie schreiben müssen, um das gewünschte Verhalten zu erzielen?
Tag, wenn

... Ich weiß nicht, auf welches Verhalten Sie im zweiten Link anspielen. Das gewünschte Ergebnis ist, dass Sie das Diagramm so korrigieren, dass der von mir erwähnte gültige (explizite) Pfad angezeigt wird. Denken Sie darüber nach: Das Diagramm deckt eine ganze Abfrage ab, aber die Frage interessiert sich nur für das WHERE->HAVINGTeil, daher denke ich, dass es viel Liebe zum Detail verdient. Wenn Sie der Meinung sind, dass meine Antwort falsch ist, bearbeiten Sie sie oder veröffentlichen Sie eine vorgeschlagene Korrektur in den Kommentaren.
Tag, wenn

12

HAVINGwird verwendet, wenn Sie ein Aggregat wie z GROUP BY.

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

8

WHERE wird als Einschränkung für den von SQL zurückgegebenen Satz angewendet. Es verwendet die in SQL integrierten Set-Oeprations und -Indizes und ist daher der schnellste Weg, um Ergebnismengen zu filtern. Verwenden Sie immer WO, wann immer dies möglich ist.

Für einige Aggregatfilter ist HAVING erforderlich. Es filtert die Abfrage, nachdem SQL die Ergebnisse abgerufen, zusammengestellt und sortiert hat. Daher ist es viel langsamer als WHERE und sollte vermieden werden, außer in den Situationen, in denen es erforderlich ist.

Mit SQL Server können Sie HAVING auch dann verwenden, wenn WHERE viel schneller ist. Tu es nicht.


Die Unterstützung für abgeleitete Tabellen in der SQL-Sprache bedeutet, dass Ihre Behauptung "HAVING ist für einige Aggregatfilter erforderlich" falsch ist.
Tag, wenn

1
Das ist ein guter Punkt. In den drei Jahren, seit ich diese Antwort geschrieben habe, bin ich sicherlich dazu übergegangen, abgeleitete Tabellen zu verwenden, in denen ich früher HAVING verwendet hätte. Ich habe nicht über die Frage nachgedacht, ob HAVING noch einige sinnvolle Anwendungsfälle hat. Ich weiß auch nicht, ob eine abgeleitete Tabelle allgemein besser abschneidet als HAVING.
Davidcl

7

Die WHERE-Klausel, die für Aggregatfunktionen nicht funktioniert,
bedeutet: Sie sollten diesen Bonus nicht wie folgt verwenden: Tabellenname

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

HIER Anstatt die WHERE-Klausel zu verwenden, müssen Sie HAVING verwenden.

Ohne die GROUP BY-Klausel funktioniert die HAVING-Klausel nur als WHERE-Klausel

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

3

Unterschied s / w WHEREund HAVINGKlausel:

Der Hauptunterschied zwischen WHEREund HAVING-Klausel besteht darin, dass WHEREsie für Zeilenoperationen und HAVINGfür Spaltenoperationen verwendet wird.

Warum brauchen wir eine HAVINGKlausel?

Wie wir wissen, können Aggregatfunktionen nur für Spalten ausgeführt werden, daher können wir in WHEREKlausel keine Aggregatfunktionen verwenden . Daher verwenden wir Aggregatfunktionen in HAVINGKlausel.


1

In einer Aggregatabfrage (Jede Abfrage, bei der eine Aggregatfunktion verwendet wird) werden Prädikate in einer where-Klausel ausgewertet, bevor die aggregierte Zwischenergebnismenge generiert wird.

Prädikate in einer Have-Klausel werden auf die aggregierte Ergebnismenge angewendet, nachdem sie generiert wurde. Aus diesem Grund müssen Prädikatbedingungen für Aggregatwerte in der Have-Klausel und nicht in der Where-Klausel platziert werden. Außerdem können Sie Aliase verwenden, die in der Select-Klausel in einer Have-Klausel definiert sind, jedoch nicht in einer Where-Klausel.


1

Ich hatte ein Problem und fand einen weiteren Unterschied zwischen WHEREund heraus HAVING. Bei indizierten Spalten funktioniert dies nicht auf die gleiche Weise.

WHERE my_indexed_row = 123 zeigt Zeilen an und führt automatisch einen "ORDER ASC" für andere indizierte Zeilen durch.

HAVING my_indexed_row = 123 zeigt alles von der ältesten "eingefügten" Zeile bis zur neuesten, keine Bestellung.


Woher wissen Sie, dass dies ein definierter Unterschied zwischen den beiden ist und kein Unfall bei der Implementierung des von Ihnen verwendeten SQL-Servers?
JdeBP

Ich habe es gerade auf MariaDB getestet. Ich denke, es war der SQL Server, den ich vor 8 Jahren verwendet habe, der zu unterschiedlichen Ergebnissen geführt hat.
Simmoniz

1

Wenn GROUP BYnicht verwendet, sind die Klauseln WHEREund HAVINGim Wesentlichen gleichwertig.

Wann GROUP BYwird jedoch verwendet:

  • Die WHEREKlausel wird verwendet, um Datensätze aus einem Ergebnis zu filtern. Die Filterung erfolgt, bevor Gruppierungen vorgenommen werden.
  • Die HAVINGKlausel wird verwendet, um Werte aus einer Gruppe zu filtern (dh um Bedingungen zu überprüfen, nachdem eine Aggregation in Gruppen durchgeführt wurde).

Ressource von hier


haben und wo sind nicht im Wesentlichen gleichwertig. es wird Fehler während der Ausführung geben. ist in der HAVING-Klausel ungültig, da sie weder in einer Aggregatfunktion noch in der GROUP BY-Klausel enthalten ist.
Nagendra Kumar

1

Eine Möglichkeit, sich das vorzustellen, ist, dass die have-Klausel ein zusätzlicher Filter zur where-Klausel ist.

Eine WHERE- Klausel filtert Datensätze aus einem Ergebnis. Der Filter wird ausgeführt, bevor Gruppierungen vorgenommen werden. Eine HAVING- Klausel wird verwendet, um Werte aus einer Gruppe zu filtern


0

Von hier aus .

Der SQL-Standard verlangt, dass HAVING nur auf Spalten in der GROUP BY-Klausel oder auf Spalten verweisen darf, die in Aggregatfunktionen verwendet werden

im Gegensatz zu der WHERE-Klausel, die auf Datenbankzeilen angewendet wird


Die Quelle sagt: "Die Verwendung von Spaltenpositionen ist veraltet, da die Syntax aus dem SQL-Standard entfernt wurde." Leider ist dies falsch: Nichts wird jemals aus dem Standard entfernt, was ironischerweise der Grund ist, warum wir noch HAVINGJahrzehnte haben, nachdem er durch abgeleitete Tabellen "veraltet" wurde.
Tag, wenn

Etwas pedantisch, aber das Anführungszeichen ist nicht korrekt, z. B. berücksichtigen SELECT 1 FROM T HAVING COUNT(*) >= 1;- verweist nicht auf Spalten in der GROUP BYKlausel (es gibt keine) oder Spalten in aggregierten Funktionen (Abfrage verweist überhaupt nicht auf Spalten).
Tag, wenn

0

Bei der Arbeit an einem Projekt war dies auch meine Frage. Wie oben angegeben, überprüft HAVING die Bedingung für das bereits gefundene Abfrageergebnis. Aber WO dient zum Überprüfen der Bedingung, während die Abfrage ausgeführt wird.

Lassen Sie mich ein Beispiel geben, um dies zu veranschaulichen. Angenommen, Sie haben eine solche Datenbanktabelle.

usertable {int userid, date datefield, int dailyincome}

Angenommen, die folgenden Zeilen befinden sich in der Tabelle:

1, 20.05.2011, 100

1, 2011-05-21, 50

1, 30.05.2011, 10

2, 30.05.2011, 10

2, 20.05.2011, 20

Jetzt wollen wir das userids bekommen und sum(dailyincome)wessensum(dailyincome)>100

Wenn wir schreiben:

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

Dies wird ein Fehler sein. Die richtige Abfrage wäre:

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


0

Die WHERE-Klausel wird zum Vergleichen von Werten in der Basistabelle verwendet, während die HAVING-Klausel zum Filtern der Ergebnisse von Aggregatfunktionen in der Ergebnismenge der Abfrage verwendet werden kann. Klicken Sie hier !


-1

Ich benutze HAVING, um eine Abfrage basierend auf den Ergebnissen einer Aggregatfunktion einzuschränken. ZB wählen Sie * in der blahblahblah-Gruppe aus, indem ETWAS zählt (ETWAS)> 0


-1

Es kann nur sein, dass das Thema "wo" eine Zeile ist, während das Thema "haben" eine Gruppe ist. Habe ich recht?


3
Sie sollten sicher sein, bevor Sie eine Antwort veröffentlichen. Dies könnte für andere irreführend sein.
pippin1289
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.