In questo articolo esploreremo quando e come utilizzare la clausola SQL PARTITION BY e la confronteremo con l'utilizzo della clausola GROUP BY.
Capire la funzione Finestra
Gli utenti del database utilizzano funzioni aggregate come MAX(), MIN(), AVERAGE() e COUNT() per eseguire l'analisi dei dati. Queste funzioni operano su un'intera tabella e restituiscono dati aggregati singoli utilizzando la clausola GROUP BY. A volte, richiediamo valori aggregati su un piccolo insieme di righe. In questo caso, la funzione Finestra combinata con la funzione di aggregazione aiuta a ottenere l'output desiderato. La funzione Window utilizza la clausola OVER() e può includere le seguenti funzioni:
- Partizione per: Questo divide le righe o il set di risultati della query in piccole partizioni.
- Ordina per: Questo dispone le righe in ordine crescente o decrescente per la finestra della partizione. L'ordine predefinito è crescente.
- Riga o intervallo: Puoi limitare ulteriormente le righe in una partizione specificando l'inizio e gli endpoint.
In questo articolo, ci concentreremo sull'esplorazione della clausola SQL PARTITION BY.
Preparazione dei dati campione
Supponiamo di avere una tabella [SalesLT].[Ordini] che memorizza i dettagli dell'ordine del cliente. Ha una colonna [Città] che specifica la città del cliente in cui è stato effettuato l'ordine.
CREATE TABLE [SalesLT].[Orders] ( orderid INT, orderdate DATE, customerName VARCHAR(100), City VARCHAR(50), amount MONEY ) INSERT INTO [SalesLT].[Orders] SELECT 1,'01/01/2021','Mohan Gupta','Alwar',10000 UNION ALL SELECT 2,'02/04/2021','Lucky Ali','Kota',20000 UNION ALL SELECT 3,'03/02/2021','Raj Kumar','Jaipur',5000 UNION ALL SELECT 4,'04/02/2021','Jyoti Kumari','Jaipur',15000 UNION ALL SELECT 5,'05/03/2021','Rahul Gupta','Jaipur',7000 UNION ALL SELECT 6,'06/04/2021','Mohan Kumar','Alwar',25000 UNION ALL SELECT 7,'07/02/2021','Kashish Agarwal','Alwar',15000 UNION ALL SELECT 8,'08/03/2021','Nagar Singh','Kota',2000 UNION ALL SELECT 9,'09/04/2021','Anil KG','Alwar',1000 Go
Diciamo che vogliamo conoscere il valore totale degli ordini per località (Città). A tale scopo, utilizziamo la funzione SUM() e GROUP BY come mostrato di seguito.
SELECT City AS CustomerCity ,sum(amount) AS totalamount FROM [SalesLT].[Orders] GROUP BY city ORDER BY city
Nel set di risultati, non possiamo utilizzare le colonne non aggregate nell'istruzione SELECT. Ad esempio, non possiamo visualizzare [CustomerName] nell'output perché non è incluso nella clausola GROUP BY.
SQL Server restituisce il seguente messaggio di errore se si tenta di utilizzare la colonna non aggregata nell'elenco delle colonne.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount FROM [SalesLT].[Orders]
Come mostrato di seguito, la clausola PARTITION BY crea una finestra più piccola (insieme di righe di dati), esegue l'aggregazione e la visualizza. In questo output puoi anche visualizzare colonne non aggregate.
Allo stesso modo, puoi utilizzare le funzioni AVG(), MIN(), MAX() per calcolare l'importo medio, minimo e massimo dalle righe in una finestra.
SELECT City AS CustomerCity, CustomerName,amount, SUM(amount) OVER(PARTITION BY city) TotalOrderAmount, Avg(amount) OVER(PARTITION BY city) AvgOrderAmount, Min(amount) OVER(PARTITION BY city) MinOrderAmount, MAX(amount) OVER(PARTITION BY city) MaxOrderAmount FROM [SalesLT].[Orders]
Utilizzo della clausola SQL PARTITION BY con la funzione ROW_NUMBER()
In precedenza, abbiamo ottenuto i valori aggregati in una finestra utilizzando la clausola PARTITION BY. Supponiamo che invece del totale, richiediamo il totale cumulativo in una partizione.
Un totale cumulativo funziona nei seguenti modi.
Riga | Totale cumulativo |
1 | Grado 1+ 2 |
2 | Classifica 2+3 |
3 | Classifica 3+4 |
Il rango della riga viene calcolato utilizzando la funzione ROW_NUMBER(). Usiamo prima questa funzione e visualizziamo i ranghi delle righe.
- La funzione ROW_NUMBER() utilizza le clausole OVER e PARTITION BY e ordina i risultati in ordine crescente o decrescente. Inizia a classificare le righe da 1 per ordine di ordinamento.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number] FROM [SalesLT].[Orders]
Ad esempio, nella città [Alwar], la riga con l'importo più alto (25000.00) è nella riga 1. Come mostrato di seguito, classifica le righe nella finestra specificata dalla clausola PARTITION BY. Ad esempio, abbiamo tre diverse città [Alwar], [Jaipur] e [Kota] e ogni finestra (città) ottiene i suoi ranghi di riga.
Per calcolare il totale cumulativo, utilizziamo i seguenti argomenti.
- RIGA CORRENTE:Specifica il punto di inizio e di fine nell'intervallo specificato.
- 1 seguente:specifica il numero di righe (1) da seguire dalla riga corrente.
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING) AS CumulativeSUM FROM [SalesLT].[Orders]
L'immagine seguente mostra che ottieni un totale cumulativo anziché un totale complessivo in una finestra specificata dalla clausola PARTITION BY.
Se utilizziamo RIGHE UNBOUNDED PRECEDENTI nella clausola SQL PARTITION BY, calcola il totale cumulativo nel modo seguente. Utilizza le righe correnti insieme alle righe con i valori più alti nella finestra specificata.
Riga | Totale cumulativo |
1 | Classifica 1 |
2 | Classificazione 1+2 |
3 | Classifica 1+2+3 |
SELECT City AS CustomerCity, CustomerName,amount, ROW_NUMBER() OVER(PARTITION BY city ORDER BY amount DESC) AS [Row Number], SUM(amount) OVER(PARTITION BY city ORDER BY amount DESC ROWS UNBOUNDED PRECEDING) AS CumulativeSUM FROM [SalesLT].[Orders]
Confronto tra la clausola GROUP BY e SQL PARTITION BY
GRUPPO PER | PARTITION BY |
Restituisce una riga per gruppo dopo aver calcolato i valori aggregati. | Restituisce tutte le righe dall'istruzione SELECT insieme a colonne aggiuntive di valori aggregati. |
Non possiamo utilizzare la colonna non aggregata nell'istruzione SELECT. | Possiamo utilizzare le colonne richieste nell'istruzione SELECT e non produce alcun errore per la colonna non aggregata. |
Richiede l'utilizzo della clausola HAVING per filtrare i record dall'istruzione SELECT. | La funzione PARTITION può avere predicati aggiuntivi nella clausola WHERE oltre alle colonne utilizzate nell'istruzione SELECT. |
Il GROUP BY viene utilizzato negli aggregati regolari. | PARTITION BY viene utilizzato negli aggregati finestrati. |
Non possiamo usarlo per calcolare i numeri di riga o i loro ranghi. | Può calcolare i numeri di riga e le loro posizioni nella finestra più piccola. |
Come utilizzarlo
Si consiglia di utilizzare la clausola SQL PARTITION BY mentre si lavora con più gruppi di dati per i valori aggregati nel singolo gruppo. Allo stesso modo, può essere utilizzato per visualizzare le righe originali con la colonna aggiuntiva di valori aggregati.