21st Jul 2022 Tempo di lettura: 6 minuti Che cos'è la clausola SQL GROUPING SETS e come si usa? Andrew Bone sql imparare sql GROUP BY ORDER BY Indice Sintassi degli insiemi di raggruppamenti SQL Esempio di SQL GROUPING SETS Esempio di ROLLUP SQL Esempio di SQL CUBE Raggruppare i dati in modo efficace con le estensioni GROUP BY di SQL Gli insiemi di raggruppamenti sono gruppi, o insiemi, di colonne in base ai quali le righe possono essere raggruppate. Invece di scrivere più query e combinare i risultati con una UNION, è possibile utilizzare semplicemente i GROUPING SETS. GROUPING SETS in SQL può essere considerata un'estensione della clausola GROUP BY. Consente di definire più insiemi di raggruppamenti nella stessa query. Vediamo la sua sintassi e come può essere equivalente a una GROUP BY con più clausole UNION ALL. Sintassi degli insiemi di raggruppamenti SQL La sintassi generale di GROUPING SETS è la seguente: SELECT aggregate_function(column_1) column_2, column_3, FROM table_name GROUP BY GROUPING SETS ( (column_2, column_3), (column_2), (column_3), () ); Si può notare come stiamo raggruppando in base ai diversi insiemi. Questa sintassi è equivalente alla seguente query più lunga che utilizza GROUP BY con UNION ALL per combinare i risultati: SELECT SUM(column_1), column_2, column_3 FROM table_name GROUP BY column_2, column_3 UNION ALL SELECT SUM(column_1), column_2, NULL FROM table_name GROUP BY column_2 UNION ALL SELECT SUM(column_1), NULL, column_3 FROM table_name GROUP BY column_3 UNION ALL SELECT SUM(column_1), NULL, NULL FROM table_name Se si utilizza GROUP BY in questo modo, sono necessarie più clausole UNION ALL per combinare i dati provenienti da fonti diverse. UNION ALL richiede inoltre che tutti gli insiemi di risultati abbiano lo stesso numero di colonne con tipi di dati compatibili, quindi è necessario adattare le query aggiungendo un valore NULL dove richiesto. Anche se la query funziona come ci si aspetta, presenta due problemi principali: È lunga e poco gestibile. Può comportare un problema di prestazioni, perché SQL deve scansionare ogni volta la tabella delle vendite. La clausola GROUPING SETS risolve questi problemi. Ma come influisce sull'output rispetto alla tradizionale clausola GROUP BY? È ora di vedere un esempio! Esempio di SQL GROUPING SETS Abbiamo bisogno di alcuni dati di esempio. Creiamo una tabella chiamata payments che contiene tutti i pagamenti ricevuti dalla nostra azienda nei mesi di gennaio, febbraio e marzo degli ultimi quattro anni, dal 2018 al 2021. Il negozio esatto in cui è avvenuto il pagamento è indicato dalla colonna store_id. Per creare questa tabella, eseguire la seguente query: CREATE TABLE payment (payment_amount decimal(8,2), payment_date date, store_id int); INSERT INTO payment VALUES (1200.99, '2018-01-18', 1), (189.23, '2018-02-15', 1), (33.43, '2018-03-03', 3), (7382.10, '2019-01-11', 2), (382.92, '2019-02-18', 1), (322.34, '2019-03-29', 2), (2929.14, '2020-01-03', 2), (499.02, '2020-02-19', 3), (994.11, '2020-03-14', 1), (394.93, '2021-01-22', 2), (3332.23, '2021-02-23', 3), (9499.49, '2021-03-10', 3), (3002.43, '2018-02-25', 2), (100.99, '2019-03-07', 1), (211.65, '2020-02-02', 1), (500.73, '2021-01-06', 3); È possibile visualizzare i dati utilizzando questa semplice clausola SELECT: SELECT * FROM payment ORDER BY payment_date; Eseguendo questa query si ottiene il risultato: payment_amountpayment_datestore_id 1200.992018-01-181 189.232018-02-151 3002.432018-02-252 33.432018-03-033 7382.102019-01-112 382.922019-02-181 100.992019-03-071 322.342019-03-292 2929.142020-01-032 211.652020-02-021 499.022020-02-193 994.112020-03-141 500.732021-01-063 394.932021-01-222 3332.232021-02-233 9499.492021-03-103 Si può notare che ci sono più voci per alcuni negozi. Immaginiamo di dover preparare un report e di voler vedere un totale per ogni negozio. La funzione aggregata SUM() può aiutarci in questo senso. Utilizzeremo anche la clausola GROUP BY per raggruppare i risultati per anno e negozio. SELECT SUM(payment_amount), YEAR(payment_date) AS 'Payment Year', store_id AS 'Store' FROM payment GROUP BY YEAR(payment_date), store_id ORDER BY YEAR(payment_date), store_id; SUM(payment_amount)Payment YearStore 1390.2220181 3002.4320182 33.4320183 483.9120191 7704.4420192 1205.7620201 2929.1420202 499.0220203 394.9320212 13332.4520213 I risultati vengono aggregati per ogni combinazione unica di anno e negozio. Tuttavia, non possiamo vedere i pagamenti totali per anno: i pagamenti totali per il 2018, 2019, 2020 o 2021. Non possiamo nemmeno vedere i totali per negozio, che sarebbe utile avere. L'utilizzo di GROUPING SETS ci permette di visualizzare questi totali. SELECT SUM(payment_amount), YEAR(payment_date) AS 'Payment Year', store_id AS 'Store' FROM payment_new GROUP BY GROUPING SETS (YEAR(payment_date), store_id) ORDER BY YEAR(payment_date), store_id; SUM(payment_amount)Payment YearStore 3079.89NULL1 14030.94NULL2 13864.90NULL3 4426.082018NULL 8188.352019NULL 4633.922020NULL 13727.382021NULL I risultati sono cambiati drasticamente! Ora vediamo solo i totali generali per ogni negozio e i totali generali per ogni anno. Per le colonne per le quali le righe non sono raggruppate, vengono visualizzati i valori NULL. Ricordare che è possibile includere più clausole GROUP BY nella propria GROUPING SETS. Applicando questo metodo alla nostra query si ottiene quanto segue: SELECT SUM(payment_amount), YEAR(payment_date) AS 'Payment Year', store_id AS 'Store' FROM payment_new GROUP BY GROUPING SETS ( (YEAR(payment_date), store_id), (YEAR(payment_date)), (store_id) ) ORDER BY YEAR(payment_date), store_id; SUM(payment_amount)Payment YearStore 3079.89NULL1 14030.94NULL2 13864.90NULL3 4426.082018NULL 1390.2220181 3002.4320182 33.4320183 8188.352019NULL 483.9120191 7704.4420192 4633.922020NULL 1205.7620201 2929.1420202 499.0220203 13727.382021NULL 394.9320212 13332.4520213 Prima di concludere questo tutorial, è opportuno menzionare altre due estensioni di SQL GROUP BY che potrebbero rivelarsi utili per un progetto o uno scenario particolare: ROLLUP e CUBE. Questi argomenti sono trattati in modo molto dettagliato in questa traccia di apprendimentoAdvanced SQL da LearnSQL.it che presenta funzioni di finestra, estensioni di GROUP BY e query ricorsive. Esempio di ROLLUP SQL Analogamente a GROUPING SETS, è possibile utilizzare l'opzione ROLLUP in una singola query per generare più insiemi di raggruppamenti. ROLLUP assume una gerarchia tra le colonne di input. Ad esempio, se le colonne di input sono: GROUP BY ROLLUP(column_1,column_2) la gerarchia è column_1 > column_2, e ROLLUP genera i seguenti set di raggruppamento: (column_1, column_2) (column_1) () ROLLUP genera tutti i gruppi di raggruppamento che hanno senso in questa gerarchia. Il programma genera una riga di subtotale ogni volta che il valore di column_1 cambia; questa è la gerarchia che abbiamo fornito. Per questo motivo, spesso si usa ROLLUP per generare subtotali e totali generali nei report. L'ordine delle colonne in ROLLUP è molto importante. Vediamo una query che utilizza ROLLUP: SELECT SUM(payment_amount), YEAR(payment_date) AS 'Payment Year', store_id AS 'Store' FROM payment GROUP BY ROLLUP (YEAR(payment_date), store_id) ORDER BY YEAR(payment_date), store_id SUM(payment_amount)Payment YearStore 30975.73NULLNULL 4426.082018NULL 1390.2220181 3002.4320182 33.4320183 8188.352019NULL 483.9120191 7704.4420192 4633.922020NULL 1205.7620201 2929.1420202 499.0220203 13727.382021NULL 394.9320212 13332.4520213 Il totale generale è mostrato nella parte superiore del risultato: 30975.73NULLNULL Il resto del risultato è strutturato come segue. Innanzitutto, viene mostrato il totale annuale: 4426.082018NULL Seguono i totali per negozio e per anno: 1390.2220181 3002.4320182 33.4320183 Come si può notare, ROLLUP genera una riga di subtotale ogni volta che il valore di Payment Year cambia, poiché questa è la gerarchia che abbiamo fornito. Questo esempio mostra quanto possa essere utile ROLLUP per la creazione di report. Esempio di SQL CUBE Simile a ROLLUP, CUBE è un'estensione della clausola GROUP BY. Consente di generare subtotali per tutte le combinazioni delle colonne di raggruppamento specificate nella clausola GROUP BY. La clausola CUBE è come una combinazione di GROUPING SETS e ROLLUP. Mostra l'output dettagliato di entrambe. SELECT SUM(payment_amount), YEAR(payment_date) AS 'Payment Year', store_id AS 'Store' FROM payment GROUP BY CUBE (YEAR(payment_date), store_id) ORDER BY YEAR(payment_date), store_id SUM(payment_amount)Payment YearStore 30975.73NULLNULL 3079.89NULL1 14030.94NULL2 13864.90NULL3 4426.082018NULL 1390.2220181 3002.4320182 33.4320183 8188.352019NULL 483.9120191 7704.4420192 4633.922020NULL 1205.7620201 2929.1420202 499.0220203 13727.382021NULL 394.9320212 13332.4520213 La differenza principale di questo output rispetto all'esempio ROLLUP è che qui viene mostrato anche il totale generale per ogni negozio. 3079.89NULL1 14030.94NULL2 13864.90NULL3 A parte queste righe, tutte le righe di questo risultato sono uguali a quelle di ROLLUP. Questo conclude il nostro confronto tra GROUPING SETS, ROLLUP e CUBE! In questo articolo troverete altri esempi di raggruppamento, rotazione e cubatura dei dati. Raggruppare i dati in modo efficace con le estensioni GROUP BY di SQL La padronanza delle estensioni SQL GROUP BY richiede un po' di pratica. Opzioni come GROUPING SETS, ROLLUP e CUBE consentono di manipolare i risultati delle query in modi diversi. Sapere come usare queste estensioni in modo efficace riduce la necessità di formattare manualmente i dati prima di trasmetterli agli stakeholder. Per approfondire le vostre conoscenze in quest'area, prendete in considerazione questo corso sulle estensioni GROUP BY di LearnSQL.it che tratta GROUPING SETS, ROLLUP e CUBE. Tags: sql imparare sql GROUP BY ORDER BY