WO vs HABEN

247

Warum müssen Sie selbst erstellte Spalten platzieren (zum Beispiel? select 1 as "number" ), HAVINGund nicht WHEREin MySQL?

Und gibt es irgendwelche Nachteile, anstatt dies zu tun WHERE 1(die gesamte Definition anstelle eines Spaltennamens zu schreiben)?

baloo
quelle

Antworten:

323

Warum müssen Sie nach HAVING Spalten erstellen, die Sie selbst erstellt haben (z. B. "1 als Zahl auswählen"), und nicht WO in MySQL?

WHEREwird vor angewendet GROUP BY, HAVINGwird nach angewendet (und kann nach Aggregaten filtern).

In der Regel können Sie Aliase in keiner dieser Klauseln verweisen, sondern MySQLermöglicht Referenzierung SELECTEbene Aliase GROUP BY, ORDER BYund HAVING.

Und gibt es irgendwelche Nachteile, anstatt "WHERE 1" zu tun (Schreiben der gesamten Definition anstelle eines Spaltennamens)?

Wenn Ihr berechneter Ausdruck keine Aggregate enthält, ist es WHEREhöchstwahrscheinlich effizienter , ihn in die Klausel einzufügen.

Quassnoi
quelle
289

Alle anderen Antworten auf diese Frage trafen nicht den entscheidenden Punkt.

Angenommen, wir haben eine Tabelle:

CREATE TABLE `table` (
 `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
 `value` int(10) unsigned NOT NULL,
 PRIMARY KEY (`id`),
 KEY `value` (`value`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8

Und haben 10 Zeilen mit ID und Wert von 1 bis 10:

INSERT INTO `table`(`id`, `value`) VALUES (1, 1),(2, 2),(3, 3),(4, 4),(5, 5),(6, 6),(7, 7),(8, 8),(9, 9),(10, 10);

Versuchen Sie die folgenden 2 Abfragen:

SELECT `value` v FROM `table` WHERE `value`>5; -- Get 5 rows
SELECT `value` v FROM `table` HAVING `value`>5; -- Get 5 rows

Sie erhalten genau die gleichen Ergebnisse. Sie können sehen, dass die HAVING-Klausel ohne die GROUP BY-Klausel funktionieren kann.


Hier ist der Unterschied:

SELECT `value` v FROM `table` WHERE `v`>5;

Fehler # 1054 - Unbekannte Spalte 'v' in 'where-Klausel'

SELECT `value` v FROM `table` HAVING `v`>5; -- Get 5 rows

Mit der WHERE-Klausel kann eine Bedingung eine beliebige Tabellenspalte verwenden, jedoch keine Aliase oder Aggregatfunktionen. Mit der HAVING-Klausel kann eine Bedingung eine ausgewählte (!) Spalte, einen Alias ​​oder eine Aggregatfunktion verwenden.

Dies liegt daran, dass die WHERE-Klausel Daten vor der Auswahl filtert, die HAVING-Klausel jedoch die resultierenden Daten nach der Auswahl filtert.

Wenn Sie also die Bedingungen in die WHERE-Klausel einfügen, ist dies effizienter, wenn Sie viele, viele Zeilen in einer Tabelle haben.

Versuchen Sie EXPLAIN, um den Hauptunterschied zu sehen:

EXPLAIN SELECT `value` v FROM `table` WHERE `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra                    |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+
|  1 | SIMPLE      | table | range | value         | value | 4       | NULL |    5 | Using where; Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+--------------------------+

EXPLAIN SELECT `value` v FROM `table` having `value`>5;
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
| id | select_type | table | type  | possible_keys | key   | key_len | ref  | rows | Extra       |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+
|  1 | SIMPLE      | table | index | NULL          | value | 4       | NULL |   10 | Using index |
+----+-------------+-------+-------+---------------+-------+---------+------+------+-------------+

Sie können sehen, ob WHERE oder HAVING den Index verwendet, aber die Zeilen sind unterschiedlich.

Fisch ertrunken
quelle
32
Ich weiß es zu schätzen, dass Sie EXPLAIN erwähnt haben!
Paiego
Da die HAVING-Klausel Daten nach der Auswahl filtert, ist die WHERE-Klausel effektiver. Wenn dies zutrifft, wann müssen wir dann HAVING anstelle von WHERE verwenden?
grep
5
@grep Wenn Sie Daten nach der Auswahl filtern müssen, benötigen Sie die HAVING-Klausel. Normalerweise verwenden wir sie mit der GROUP BY-Klausel, z. B.: SELECT value, COUNT(*) frequency FROM table GROUP BY value HAVING frequency > 10
Fishdrowned
1
Ausgezeichnete Post. Ein paar vorgeschlagene Klarstellungen: Wechsel ...HAVING clause can use both column and alias.zu ...HAVING clause can use either column or alias.und Wechsel ...WHERE clause will be more effectivezu...WHERE clause will be more efficient
rmirabelle
2
Die HAVING-Klausel wurde zu SQL hinzugefügt, da das Schlüsselwort WHERE nicht mit Aggregatfunktionen verwendet werden konnte.
Shashank Vivek
62

Der Hauptunterschied besteht darin, dass WHEREnicht für gruppierte Elemente (wie z. B. SUM(number)) verwendet werden kannHAVING kann, ist.

Der Grund dafür ist das WHEREgeschehen ist , bevor die Gruppierung und HAVINGerfolgt nach der Gruppierung erfolgt.

David Brunelle
quelle
39

HAVINGwird verwendet, um nach Aggregationen in Ihrem zu filtern GROUP BY.

So suchen Sie beispielsweise nach doppelten Namen:

SELECT Name FROM Usernames
GROUP BY Name
HAVING COUNT(*) > 1
Kevin McKelvin
quelle
1
Es ist bis zu einem gewissen Grad wahr. Sie können immer noch Ihr ganzes 'Wo' in die Haben-Klausel einfügen.
David Brunelle
8

Diese 2 fühlen sich wie die ersten an, da beide verwendet werden, um über eine Bedingung zum Filtern von Daten zu sprechen. Obwohl wir in jedem Fall "Haben" anstelle von "Wo" verwenden können, gibt es Fälle, in denen wir "Wo" nicht anstelle von "Haben" verwenden können. Dies liegt daran, dass in einer Auswahlabfrage 'wobei' Daten vor 'Auswahl' filtert, während 'Daten nach' Auswahl 'gefiltert werden. Wenn wir also Aliasnamen verwenden, die sich nicht in der Datenbank befinden, kann 'wo' sie nicht identifizieren, aber 'haben' kann.

Beispiel: Lassen Sie die Tabelle Student student_id, Name, Geburtstag, Adresse enthalten. Angenommen, der Geburtstag ist vom Typ Datum.

SELECT * FROM Student WHERE YEAR(birthday)>1993; /*this will work as birthday is in database.if we use having in place of where too this will work*/

SELECT student_id,(YEAR(CurDate())-YEAR(birthday)) AS Age FROM Student HAVING Age>20; 
/*this will not work if we use ‘where’ here, ‘where’ don’t know about age as age is defined in select part.*/
Nuwantha
quelle
1
Dieses Beispiel aus dem wirklichen Leben verdeutlicht den Unterschied zwischen WHEREund vollständig HAVING.
WM
Zeigt deutlich den Unterschied zwischen Haben und Wo. Vielen Dank.
MarcoZen
3

WHERE filtert vor der Gruppierung von Daten und HAVING filtert nach der Gruppierung von Daten. Dies ist eine wichtige Unterscheidung; Zeilen, die durch eine WHERE- Klausel entfernt werden, werden nicht in die Gruppe aufgenommen. Dies könnte die berechneten Werte ändern, was wiederum (= als Ergebnis) beeinflussen könnte, welche Gruppen basierend auf der Verwendung dieser Werte in der HAVING- Klausel gefiltert werden .

Und weiter,

HAVING ist WHERE so ähnlich, dass die meisten DBMS sie als dasselbe behandeln, wenn kein GROUP BY angegeben ist. Trotzdem sollten Sie diese Unterscheidung selbst treffen. Verwenden Sie HAVING nur in Verbindung mit GROUP BY- Klauseln. Verwenden Sie WHERE für die Standardfilterung auf Zeilenebene.

Auszug aus: Forta, Ben. "Sams bringt sich SQL in 10 Minuten bei (5. Ausgabe) (Sams bringt sich selbst bei ...)."

snr
quelle
1

Haben wird nur mit Aggregation verwendet, aber wo mit Nicht-Aggregationsanweisungen.

Hos Mercury
quelle