Articles

MySQL :: MySQL 5.6 Manuale di Riferimento :: 12.19.3 MySQL Gestione del GRUPPO DA

12.19.3 MySQL Gestione del GRUPPO DA parte di

In SQL standard, una query che include un GROUP BY clausola non può fare riferimento a nonaggregated colonne dell’elenco di selezione che non sono denominati nel GROUP BY clausola. Ad esempio, questa query è illegale in SQL standard perché la colonna non segregata name nell’elenco di selezione non viene visualizzata 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;

Affinché la query sia legale, la colonna namedeve essere omessa dall’elenco di selezione o nominata nella clausola GROUP BY.

MySQL estende l’uso SQL standard di GROUP BYin modo che l’elenco di selezione possa fare riferimento a colonne non aggregate non nominate nella clausolaGROUP BY. Ciò significa che la query precedente è legale in MySQL. È possibile utilizzare questa funzione per ottenere prestazioni migliori evitando l’ordinamento e il raggruppamento delle colonne non necessari. Tuttavia, questo è utile principalmente quando tutti i valori in ogni colonna non aggregata non denominata in GROUP BY sono gli stessi per ogni gruppo. Il server è libero di scegliere qualsiasi valore da ciascun gruppo, quindi a meno che non siano uguali, i valori scelti non sono deterministici. Inoltre, la selezione dei valori di ciascun gruppo non può essere influenzata aggiungendo una clausolaORDER BY. L’ordinamento dei set di risultati si verifica dopo la scelta dei valori e ORDER BY non influisce sui valori all’interno di ciascun gruppo scelto dal server.

Un’estensione MySQL simile si applica alla clausolaHAVING. In SQL standard, una query non può fare riferimento a colonne non aggregate nella clausolaHAVING che non sono nominate nella clausolaGROUP BY. Per semplificare i calcoli, un’estensione MySQL consente riferimenti a tali colonne. Questa estensione presuppone che le colonne non raggruppate abbiano gli stessi valori di gruppo. Altrimenti, il risultato è non deterministico.

Per disabilitare l’estensione MySQL GROUP BYe abilitare il comportamento SQL standard, abilitare la modalità SQL ONLY_FULL_GROUP_BY. In questo caso, le colonne non nominate nella clausola GROUP BY non possono essere utilizzate nella clausola select list o HAVING a meno che non siano racchiuse in una funzione aggregata.

L’estensione select list si applica anche a ORDER BY. Cioè, è possibile fare riferimento a colonne non aggregate nella clausola ORDER BY che non appaiono nella clausola GROUP BY. (Tuttavia, come accennato in precedenza,ORDER BY non influisce sui valori scelti dalle colonne non segregate; li ordina solo dopo che sono stati scelti.) Questa estensione non si applica se la modalità SQLONLY_FULL_GROUP_BY è abilitata.

Se una query ha funzioni aggregate e nessuna clausola GROUP BY, non può avere colonne non aggregate nell’elenco di selezione,HAVING condizione, o ORDER BY elenco con ONLY_FULL_GROUP_BY abilitato:

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

Senza GROUP BY, esiste un singolo gruppo e non è deterministico quale valore name scegliere per il gruppo.

Un’altra estensione MySQL per SQL standard consente riferimenti nella clausolaHAVING alle espressioni con alias nell’elenco select. Abilitare ONLY_FULL_GROUP_BY impedisce questo. Ad esempio, la seguente query restituiscename valori che si verificano solo una volta nella tabella orders; la query viene accettata indipendentemente dal fatto che ONLY_FULL_GROUP_BY sia abilitata:

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

La seguente query viene accettata solo se ONLY_FULL_GROUP_BY è disabilitata.

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

Se si sta tentando di seguire SQL standard, è possibile utilizzare solo espressioni di colonna nelle clausoleGROUP BY. Come soluzione alternativa, utilizzare un alias per l’espressione:

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

MySQL consente espressioni non di colonna in GROUP BY clausole, quindi l’alias non è necessario:

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