Articles

MySQL :: MySQL 5.6 Reference Manual :: 12.19.3 MySQL Handling of GROUP BY

12.19.3 MySQL Handling of GROUP BY

in standard SQL kan een query die een GROUP BYclausule bevat niet verwijzen naar niet-aggregated columns in de select list die niet genoemd worden in deGROUP BYclausule. Deze query is bijvoorbeeld illegaal in standaard SQL omdat de niet-samengevoegde name kolom in de select lijst niet voorkomt in de 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;

om de zoekopdracht legaal te maken, moet de kolom name worden weggelaten uit de select list of worden genoemd in de GROUP BY clausule.

MySQL breidt het standaard SQL gebruik van GROUP BY uit zodat de select lijst kan verwijzen naar niet-samengevoegde kolommen die niet genoemd zijn in de GROUP BY clausule. Dit betekent dat de voorgaande query legaal is in MySQL. U kunt deze functie gebruiken om betere prestaties te krijgen door onnodig sorteren en groeperen van kolommen te vermijden. Dit is echter vooral nuttig wanneer alle waarden in elke niet-geaggregeerde kolom die niet genoemd wordt in de GROUP BY voor elke groep hetzelfde zijn. De server is vrij om elke waarde uit elke groep te kiezen, dus tenzij ze hetzelfde zijn, zijn de gekozen waarden niet-deterministisch. Bovendien kan de selectie van waarden uit elke groep niet worden beïnvloed door het toevoegen van een ORDER BY clausule. Het sorteren van de resultaatset vindt plaats nadat waarden zijn gekozen, en ORDER BY heeft geen invloed op welke waarden binnen elke groep de server kiest.

een soortgelijke MySQL extensie is van toepassing op de HAVING clausule. In standaard SQL kan een query niet verwijzen naar niet-samengevoegde kolommen in de HAVING clausule die niet genoemd worden in de GROUP BY clausule. Om berekeningen te vereenvoudigen, staat een MySQL extensie verwijzingen naar dergelijke kolommen toe. Deze extensie gaat ervan uit dat de niet-gegroepeerde kolommen dezelfde groepswaarden hebben. Anders is het resultaat niet-deterministisch.

om de MySQL GROUP BY extensie uit te schakelen en standaard SQL-gedrag aan te zetten, schakelt u de ONLY_FULL_GROUP_BY SQL-modus in. In dit geval kunnen kolommen die niet zijn genoemd in de GROUP BY – clausule niet worden gebruikt in de select list of HAVING – clausule, tenzij ze zijn ingesloten in een aggregaatfunctie.

de extensie select list is ook van toepassing op ORDER BY. Dat wil zeggen, U kunt verwijzen naar niet-samengevoegde kolommen in de ORDER BY clausule die niet voorkomen in de GROUP BY clausule. (Echter, zoals eerder vermeld, heeft ORDER BY geen invloed op welke waarden worden gekozen uit niet-geaggregeerde kolommen; het sorteert ze alleen nadat ze zijn gekozen.) Deze extensie is niet van toepassing als de ONLY_FULL_GROUP_BY SQL-modus is ingeschakeld.

als een query geaggregeerde functies heeft en geen GROUP BY clausule, kan het geen niet-geaggregeerde kolommen in de select lijst hebben, HAVING voorwaarde, of ORDER BY lijst met ONLY_FULL_GROUP_BY ingeschakeld:

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

zonder GROUP BY is er één groep en het is niet-deterministisch welke name waarde voor de groep moet worden gekozen.

een andere MySQL-extensie voor standaard SQL staat verwijzingen toe in de HAVING clausule naar aliased expressies in de select lijst. Het inschakelen van ONLY_FULL_GROUP_BY voorkomt dit. De volgende query geeft bijvoorbeeld name waarden terug die slechts één keer voorkomen in tabel orders; de query wordt geaccepteerd ongeacht of ONLY_FULL_GROUP_BY is ingeschakeld:

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

de volgende query wordt alleen geaccepteerd als ONLY_FULL_GROUP_BY is uitgeschakeld.

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

Als u probeert standaard SQL te volgen, kunt u alleen kolomuitdrukkingen gebruiken in GROUP BY clausules. Gebruik als tijdelijke oplossing een alias voor de uitdrukking:

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

MySQL staat niet-kolomn expressies toe in GROUP BY clausules, zodat de alias niet nodig is:

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