Articles

MySQL :: MySQL 5.6 Referenzhandbuch :: 12.19.3 MySQL-Handhabung von GROUP BY

12.19.3 MySQL-Handhabung von GROUP BY

In Standard-SQL kann eine Abfrage, die eine GROUP BY -Klausel enthält, nicht auf nicht aggregierte Spalten in der Select-Liste verweisen, die nicht in der GROUP BY Klausel. Diese Abfrage ist beispielsweise in Standard-SQL nicht zulässig, da die Spalte nonaggregated name in der Auswahlliste nicht in GROUP BY:

SELECT o.custid, c.name, MAX(o.payment) FROM orders AS o, customers AS c WHERE o.custid = c.custid GROUP BY o.custid;

Damit die Abfrage zulässig ist, muss die Spalte name in der select-Liste weggelassen oder in der Klausel GROUP BY benannt werden.

MySQL erweitert die standardmäßige SQL-Verwendung von GROUP BY, sodass die select-Liste auf nicht aggregierte Spalten verweisen kann, die nicht in der GROUP BY -Klausel benannt sind. Dies bedeutet, dass die vorhergehende Abfrage in MySQL legal ist. Sie können diese Funktion verwenden, um eine bessere Leistung zu erzielen, indem Sie unnötige Spaltensortierung und -gruppierung vermeiden. Dies ist jedoch vor allem dann nützlich, wenn alle Werte in jeder nicht aggregierten Spalte, die nicht in GROUP BY sind, für jede Gruppe gleich sind. Dem Server steht es frei, einen beliebigen Wert aus jeder Gruppe auszuwählen, sodass die ausgewählten Werte nicht deterministisch sind, es sei denn, sie sind gleich. Darüber hinaus kann die Auswahl der Werte aus jeder Gruppe nicht durch Hinzufügen einer ORDER BY Klausel beeinflusst werden. Die Ergebnismengensortierung erfolgt, nachdem Werte ausgewählt wurden, und ORDER BY hat keinen Einfluss darauf, welche Werte innerhalb jeder Gruppe der Server auswählt.

Eine ähnliche MySQL-Erweiterung gilt für die HAVING-Klausel. In Standard-SQL kann eine Abfrage nicht auf nicht aggregierte Spalten in der HAVING -Klausel verweisen, die nicht in der GROUP BY -Klausel benannt sind. Um Berechnungen zu vereinfachen, erlaubt eine MySQL-Erweiterung Verweise auf solche Spalten. Diese Erweiterung setzt voraus, dass die nicht gruppierten Spalten dieselben gruppenweisen Werte haben. Andernfalls ist das Ergebnis nicht deterministisch.

Um die MySQL GROUP BY-Erweiterung zu deaktivieren und das Standard-SQL-Verhalten zu aktivieren, aktivieren Sie den ONLY_FULL_GROUP_BY SQL-Modus. In diesem Fall können Spalten, die nicht in der GROUP BY -Klausel benannt sind, nicht in der select-Liste oder HAVING -Klausel verwendet werden, es sei denn, sie sind in einer Aggregatfunktion eingeschlossen.

Die Erweiterung select list gilt auch für ORDER BY. Das heißt, Sie können auf nicht aggregierte Spalten in der ORDER BY -Klausel verweisen, die nicht in der GROUP BY -Klausel vorkommen. (Wie bereits erwähnt, hat ORDER BY jedoch keinen Einfluss darauf, welche Werte aus nicht aggregierten Spalten ausgewählt werden.) Diese Erweiterung gilt nicht, wenn der ONLY_FULL_GROUP_BY SQL-Modus aktiviert ist.

Wenn eine Abfrage Aggregatfunktionen und keine GROUP BY Klausel hat, kann sie keine nicht aggregierten Spalten in der Select-Liste haben, HAVING Bedingung oder ORDER BY Liste mit ONLY_FULL_GROUP_BY aktiviert:

mysql> SELECT name, MAX(age) FROM t;ERROR 1140 (42000): Mixing of GROUP columns (MIN(),MAX(),COUNT(),...)with no GROUP columns is illegal if there is no GROUP BY clause

Ohne GROUP BY gibt es eine einzelne Gruppe und es ist nicht deterministisch, welcher name Wert für die Gruppe ausgewählt werden soll.

Eine weitere MySQL-Erweiterung für Standard-SQL erlaubt Verweise in der HAVING-Klausel auf Aliasausdrücke in der Select-Liste. Das Aktivieren von ONLY_FULL_GROUP_BY verhindert dies. Die folgende Abfrage gibt beispielsweise name Werte zurück, die nur einmal in der Tabelle vorkommen orders; die Abfrage wird unabhängig davon akzeptiert, ob ONLY_FULL_GROUP_BY aktiviert ist:

SELECT name, COUNT(name) FROM orders GROUP BY name HAVING COUNT(name) = 1;

Die folgende Abfrage wird nur akzeptiert, wenn ONLY_FULL_GROUP_BY deaktiviert ist.

SELECT name, COUNT(name) AS c FROM orders GROUP BY name HAVING c = 1;

Wenn Sie versuchen, Standard-SQL zu befolgen, können Sie nur Spaltenausdrücke in GROUP BY -Klauseln verwenden. Verwenden Sie zur Problemumgehung einen Alias für den Ausdruck:

SELECT id, FLOOR(value/100) AS val FROM tbl_name GROUP BY id, val;

MySQL erlaubt Nicht-Spaltenausdrücke in GROUP BY -Klauseln, sodass der Alias nicht erforderlich ist:

SELECT id, FLOOR(value/100) FROM tbl_name GROUP BY id, FLOOR(value/100);