SELECT - GROUP BY- Transact-SQL
Si applica a: SQL Server Database SQL di Azure Istanza gestita di SQL di Azure Azure Synapse Analytics Piattaforma di strumenti analitici (PDW) Endpoint di analisi SQL in Microsoft Fabric Warehouse in Microsoft Fabric
Clausola di istruzione SELECT che divide il risultato della query in gruppi di righe, in genere eseguendo una o più aggregazioni in ogni gruppo. L'istruzione SELECT restituisce una riga per ogni gruppo.
Sintassi
Convenzioni relative alla sintassi Transact-SQL
-- Syntax for SQL Server and Azure SQL Database
-- ISO-Compliant Syntax
GROUP BY {
column-expression
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )
| GROUPING SETS ( <grouping_set> [ ,...n ] )
| () --calculates the grand total
} [ ,...n ]
<group_by_expression> ::=
column-expression
| ( column-expression [ ,...n ] )
<grouping_set> ::=
() --calculates the grand total
| <grouping_set_item>
| ( <grouping_set_item> [ ,...n ] )
<grouping_set_item> ::=
<group_by_expression>
| ROLLUP ( <group_by_expression> [ ,...n ] )
| CUBE ( <group_by_expression> [ ,...n ] )
-- For backward compatibility only.
-- Non-ISO-Compliant Syntax for SQL Server and Azure SQL Database
GROUP BY {
ALL column-expression [ ,...n ]
| column-expression [ ,...n ] WITH { CUBE | ROLLUP }
}
-- Syntax for Azure Synapse Analytics
GROUP BY {
column-name [ WITH (DISTRIBUTED_AGG) ]
| column-expression
| ROLLUP ( <group_by_expression> [ ,...n ] )
} [ ,...n ]
-- Syntax for Parallel Data Warehouse
GROUP BY {
column-name [ WITH (DISTRIBUTED_AGG) ]
| column-expression
} [ ,...n ]
Argomenti
column-expression
Specifica una colonna o un calcolo di non aggregazione in una colonna. Questa colonna può appartenere a una tabella, una tabella derivata o una visualizzazione. La colonna deve essere presente nella clausola FROM dell'istruzione SELECT, ma non è necessario che sia inclusa nell'elenco SELECT.
Per le espressioni valide, vedere Espressioni.
La colonna deve essere presente nella clausola FROM dell'istruzione SELECT, ma non è necessario che sia inclusa nell'elenco SELECT. Tuttavia, ogni colonna della tabella o della visualizzazione di qualsiasi espressione di non aggregazione presente nell'elenco <select> deve essere inclusa nell'elenco GROUP BY:
Le istruzioni seguenti sono consentite:
SELECT ColumnA, ColumnB FROM T GROUP BY ColumnA, ColumnB;
SELECT ColumnA + ColumnB FROM T GROUP BY ColumnA, ColumnB;
SELECT ColumnA + ColumnB FROM T GROUP BY ColumnA + ColumnB;
SELECT ColumnA + ColumnB + constant FROM T GROUP BY ColumnA, ColumnB;
Le istruzioni seguenti non sono consentite:
SELECT ColumnA, ColumnB FROM T GROUP BY ColumnA + ColumnB;
SELECT ColumnA + constant + ColumnB FROM T GROUP BY ColumnA + ColumnB;
L'espressione della colonna non può contenere:
- L'alias di una colonna definita nell'elenco SELECT. Può usare l'alias di una colonna per una tabella derivata definita nella clausola FROM.
- Una colonna di tipo text, ntext o image. È possibile tuttavia usare una colonna text, ntext o image come argomento di una funzione che restituisce un valore di un tipo di dati valido. Ad esempio, l'espressione può usare SUBSTRING() e CAST(). Ciò si applica anche alle espressioni nella clausola HAVING.
- metodi con tipo di dati xml. Può includere una funzione definita dall'utente che usa metodi con tipo di dati xml. Può includere una colonna calcolata che usa metodi con tipo di dati xml.
- Sottoquery. Viene restituito l'errore 144.
- Una colonna di una visualizzazione indicizzata.
GROUP BY column-expression [ ,...n ]
Raggruppa i risultati dell'istruzione SELECT in base ai valori in un elenco di una o più espressioni di colonna.
Ad esempio, questa query crea una tabella Sales con colonne per Country, Region e Sales. Inserisce quattro righe, due delle quali con valori corrispondenti per Country e Region.
CREATE TABLE Sales ( Country VARCHAR(50), Region VARCHAR(50), Sales INT );
INSERT INTO sales VALUES (N'Canada', N'Alberta', 100);
INSERT INTO sales VALUES (N'Canada', N'British Columbia', 200);
INSERT INTO sales VALUES (N'Canada', N'British Columbia', 300);
INSERT INTO sales VALUES (N'United States', N'Montana', 100);
La tabella Sales contiene le righe seguenti:
Country | Area | Vendite |
---|---|---|
Canada | Alberta | 100 |
Canada | British Columbia | 200 |
Canada | British Columbia | 300 |
Stati Uniti | Montana | 100 |
La query successiva raggruppa Country e Region e restituisce la somma aggregata per ogni combinazione di valori.
SELECT Country, Region, SUM(sales) AS TotalSales
FROM Sales
GROUP BY Country, Region;
Il risultato della query ha 3 righe perché sono presenti 3 combinazioni di valori per Country e Region. Il valore TotalSales per Canada e British Columbia è la somma di due righe.
Country | Paese | TotalSales |
---|---|---|
Canada | Alberta | 100 |
Canada | British Columbia | 500 |
Stati Uniti | Montana | 100 |
GROUP BY ROLLUP
Crea un gruppo per ogni combinazione di espressioni di colonna. Esegue anche il rollup dei risultati in subtotali e totali complessivi. Per eseguire questa operazione, esegue uno spostamento da destra a sinistra riducendo il numero di espressioni di colonna su cui crea gruppi e aggregazioni.
L'ordine delle colonne ha effetto sull'output di ROLLUP e può avere effetto sul numero di righe nel set di risultati.
Ad esempio, GROUP BY ROLLUP (col1, col2, col3, col4)
crea gruppi per ogni combinazione di espressioni di colonna negli elenchi seguenti.
- col1, col2, col3, col4
- col1, col2, col3, NULL
- col1, col2, NULL, NULL
- col1, NULL, NULL, NULL
- NULL, NULL, NULL, NULL --Totale complessivo
Usando la tabella dell'esempio precedente, questo codice esegue un'operazione GROUP BY ROLLUP anziché una semplice operazione GROUP BY.
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY ROLLUP (Country, Region);
Il risultato della query ha le stesse aggregazioni di GROUP BY senza ROLLUP. Inoltre, crea i subtotali per ogni valore di Country. Infine, visualizza un totale complessivo per tutte le righe. Il risultato è simile al seguente:
Country | Paese | TotalSales |
---|---|---|
Canada | Alberta | 100 |
Canada | British Columbia | 500 |
Canada | NULL | 600 |
Stati Uniti | Montana | 100 |
Stati Uniti | NULL | 100 |
NULL | NULL | 700 |
GROUP BY CUBE ( )
GROUP BY CUBE crea gruppi per tutte le possibili combinazioni di colonne. Per GROUP BY CUBE (a, b) il risultato include gruppi per i valori univoci di (a, b), (NULL, b), (a, NULL) e (NULL, NULL).
Usando la tabella degli esempi precedenti, questo codice esegue un'operazione GROUP BY CUBE in Country e Region.
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY CUBE (Country, Region);
Il risultato della query include gruppi per i valori univoci di (Country, Region), (NULL, Region), (Country, NULL) e (NULL, NULL). I risultati sono simili ai seguenti:
Country | Paese | TotalSales |
---|---|---|
Canada | Alberta | 100 |
NULL | Alberta | 100 |
Canada | British Columbia | 500 |
NULL | British Columbia | 500 |
Stati Uniti | Montana | 100 |
NULL | Montana | 100 |
NULL | NULL | 700 |
Canada | NULL | 600 |
Stati Uniti | NULL | 100 |
GROUP BY GROUPING SETS ( )
L'opzione GROUPING SETS consente di combinare più clausole GROUP BY in un'unica clausola GROUP BY. I risultati rappresentano l'equivalente di quelli della clausola UNION ALL dei gruppi specificati.
Ad esempio, GROUP BY ROLLUP (Country, Region)
e GROUP BY GROUPING SETS ( ROLLUP (Country, Region) )
restituiscono gli stessi risultati.
Quando GROUPING SETS ha due o più elementi, i risultati sono un'unione degli elementi. Questo esempio restituisce l'unione dei risultati di ROLLUP e CUBE per Country e Region.
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY GROUPING SETS ( ROLLUP (Country, Region), CUBE (Country, Region) );
I risultati sono gli stessi di questa query che restituisce un'unione delle due istruzioni GROUP BY.
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY ROLLUP (Country, Region)
UNION ALL
SELECT Country, Region, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY CUBE (Country, Region);
SQL non consolida i gruppi duplicati generati per un elenco GROUPING SETS. Ad esempio, in GROUP BY ( (), CUBE (Country, Region) )
entrambi gli elementi restituiscono una riga per il totale complessivo ed entrambe le righe saranno elencate nei risultati.
GROUP BY ()
Specifica il gruppo vuoto, che genera il totale complessivo. Ha la stessa funzione di uno degli elementi di GROUPING SET. Ad esempio, questa istruzione fornisce le vendite totali per ogni paese/area geografica e quindi assegna il totale complessivo per tutti i paesi/aree geografiche.
SELECT Country, SUM(Sales) AS TotalSales
FROM Sales
GROUP BY GROUPING SETS ( Country, () );
GROUP BY ALL column-expression [ ,...n ]
Si applica a: SQL Server e database SQL di Azure
Nota
questa sintassi è disponibile solo per la compatibilità con le versioni precedenti. Verrà rimossa in una versione futura. Evitare pertanto di usarla in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni che attualmente usano questa sintassi.
Specifica di includere tutti i gruppi nei risultati indipendentemente dal fatto che soddisfino i criteri di ricerca nella clausola WHERE. I gruppi che non soddisfano i criteri di ricerca hanno valore NULL per l'aggregazione.
GROUP BY ALL:
- Questa operazione non è supportata in query che accedono a tabelle remote se la query include anche una clausola WHERE.
- L'operazione avrà esito negativo nelle colonne con l'attributo FILESTREAM.
GROUP BY column-expression [ ,...n ] WITH { CUBE | ROLLUP }
Si applica a: SQL Server e database SQL di Azure
Nota
questa sintassi è disponibile solo per la compatibilità con le versioni precedenti. Evitare pertanto di usarla in un nuovo progetto di sviluppo e prevedere interventi di modifica nelle applicazioni che attualmente usano questa sintassi.
WITH (DISTRIBUTED_AGG)
Si applica a: Azure Synapse Analytics, Piattaforma di strumenti analitici (PDW)
L'hint per la query DISTRIBUTED_AGG forza nel sistema di elaborazione parallela elevata (Massively Parallel Processing, MPP) la ridistribuzione di una tabella in una colonna specifica prima dell'esecuzione di un'aggregazione. Solo una colonna della clausola GROUP BY può avere un hint per la query DISTRIBUTED_AGG. Al termine dell'esecuzione della query, la tabella ridistribuita viene eliminata. La tabella originale non viene modificata.
NOTA: l'hint per la query DISTRIBUTED_AGG è incluso per la compatibilità con le versioni precedenti della piattaforma di strumenti analitici e non migliora le prestazioni per la maggior parte delle query. Per impostazione predefinita, MPP distribuisce già i dati in base alle esigenze per migliorare le prestazioni per le aggregazioni.
Osservazioni generali
Interazione di GROUP BY con l'istruzione SELECT
Elenco SELECT:
- Aggregazione di vettori. Se l'elenco SELECT include funzioni di aggregazione, la clausola GROUP BY calcola un valore di riepilogo per ogni gruppo. Tali funzioni sono denominate aggregazioni vettoriali.
- Aggregazioni DISTINCT. Le aggregazioni AVG (DISTINCT column_name), COUNT (DISTINCT column_name) e SUM (DISTINCT column_name) sono supportate con ROLLUP, CUBE e GROUPING SETS.
Clausola WHERE:
- SQL rimuove le righe che non soddisfano le condizioni presenti nella clausola WHERE prima che venga eseguita qualsiasi operazione di raggruppamento.
Clausola HAVING:
- SQL usa la clausola HAVING per filtrare i gruppi nel set di risultati.
Clausola ORDER BY:
- Per eseguire questa operazione, utilizzare la clausola ORDER BY. La clausola GROUP BY non ordina il set di risultati.
Valori NULL:
- Se una colonna di raggruppamento contiene valori NULL, tutti i valori NULL vengono considerati uguali e vengono raccolti in un singolo gruppo.
Limitazioni e restrizioni
Si applica a: SQL Server (a partire dalla versione 2008) e Azure Synapse Analytics
Capacità massima
Per una clausola GROUP BY che usa ROLLUP, CUBE o GROUPING SETS, il numero massimo di espressioni è 32. Il numero massimo di gruppi è 4096 (212). Gli esempi seguenti non possono essere eseguiti correttamente perché la clausola GROUP BY ha più di 4096 gruppi.
L'esempio seguente genera 4097 (212 + 1) set di raggruppamenti e ha esito negativo.
GROUP BY GROUPING SETS( CUBE(a1, ..., a12), b )
L'esempio seguente genera 4097 (212 + 1) gruppi e ha esito negativo. Sia
CUBE ()
che il()
set di raggruppamento producono una riga totale completa e i set di raggruppamento duplicati non vengono eliminati.GROUP BY GROUPING SETS( CUBE(a1, ..., a12), ())
Questo esempio usa la sintassi compatibile con le versioni precedenti. Genera 8192 (213) set di raggruppamenti e ha esito negativo.
GROUP BY CUBE (a1, ..., a13) GROUP BY a1, ..., a13 WITH CUBE
Per le clausole GROUP BY compatibili con le versioni precedenti che non contengono CUBE o ROLLUP, il numero di elementi raggruppati per elementi è limitato dalle dimensioni delle colonne GROUP BY, dalle colonne aggregate e dai valori aggregati coinvolti nella query. Tale limite è correlato al limite di 8.060 byte della tabella di lavoro intermedia necessaria per mantenere i risultati intermedi delle query. Quando viene specificato l'operatore CUBE o ROLLUP, sono consentite al massimo 12 espressioni di raggruppamento.
Supporto per le funzionalità GROUP BY di SQL-2006 ISO e ANSI
La clausola GROPU BY supporta tutte le funzionalità GROUP BY incluse nello standard SQL-2006 con le eccezioni di sintassi seguenti:
I set di raggruppamento non sono consentiti nella clausola GROUP BY, a meno che non facciano parte di un elenco GROUPING SETS esplicito. Ad esempio,
GROUP BY Column1, (Column2, ...ColumnN
) è consentito nello standard ma non in Transact-SQL. Transact-SQL supportaGROUP BY C1, GROUPING SETS ((Column2, ...ColumnN))
eGROUP BY Column1, Column2, ... ColumnN
che sono semanticamente equivalenti. Queste espressioni sono semanticamente equivalenti a quelle dell'esempio relativo aGROUP BY
precedente. Ciò consente di evitare la possibilità cheGROUP BY Column1, (Column2, ...ColumnN
) venga interpretato erroneamente comeGROUP BY C1, GROUPING SETS ((Column2, ...ColumnN))
, che non sono semanticamente equivalenti.I set di raggruppamento non sono consentiti all'interno di set di raggruppamento. Ad esempio,
GROUP BY GROUPING SETS (A1, A2,...An, GROUPING SETS (C1, C2, ...Cn))
è consentito nello standard SQL-2006 ma non in Transact-SQL.GROUP BY GROUPING SETS( A1, A2,...An, C1, C2, ...Cn )
oGROUP BY GROUPING SETS( (A1), (A2), ... (An), (C1), (C2), ... (Cn) )
sono consentiti in Transact-SQL e sono semanticamente equivalenti al primo esempio di GROUP BY ma hanno una sintassi più chiara.GROUP BY [ALL/DISTINCT] è consentito solo in una clausola GROUP BY semplice che contiene espressioni di colonna. Non è consentito con i costrutti GROUPING SETS, ROLLUP, CUBE, WITH CUBE o WITH ROLLUP. ALL è il valore predefinito ed è implicito. È anche consentito solo nella sintassi compatibile con le versioni precedenti.
Confronto tra le funzionalità GROUP BY supportate
La tabella seguente descrive le funzionalità GROUP BY supportate in base alle versioni SQL e al livello di compatibilità del database.
Funzionalità | SQL Server Integration Services | Livello di compatibilità di SQL Server 100 o superiore | Livello di compatibilità di SQL Server 2008 o versioni successive pari a 90. |
---|---|---|---|
Aggregazioni DISTINCT | Non supportate per WITH CUBE o WITH ROLLUP. | Supportate per WITH CUBE, WITH ROLLUP, GROUPING SETS, CUBE o ROLLUP. | Comportamento analogo al livello di compatibilità pari a 100. |
Funzione definita dall'utente denominata CUBE o ROLLUP nella clausola GROUP BY | La funzione definita dall'utente dbo.cube(arg1,...argN) o dbo.rollup(arg1,...argN) nella clausola GROUP BY è consentita. Ad esempio: SELECT SUM (x) FROM T GROUP BY dbo.cube(y); |
La funzione definita dall'utente dbo.cube (arg1,...argN**)** o dbo.rollup(arg1,...argN) nella clausola GROUP BY non è consentita. Ad esempio: SELECT SUM (x) FROM T GROUP BY dbo.cube(y); Viene restituito il messaggio di errore seguente: "Sintassi non corretta vicino alla parola chiave 'cube'|' rollup". Per evitare questo problema, sostituire dbo.cube con [dbo].[cube] oppure dbo.rollup con [dbo].[rollup] .L'esempio seguente è consentito: SELECT SUM (x) FROM T GROUP BY [dbo].[cube](y); |
La funzione definita dall'utente dbo.cube (arg1,...argN) o dbo.rollup(arg1,...argN) nella clausola GROUP BY è consentita Ad esempio: SELECT SUM (x) FROM T GROUP BY dbo.cube(y); |
GROUPING SETS | Non supportato | Supportata | Supportata |
CUBE | Non supportato | Supportato | Non supportato |
ROLLUP | Non supportato | Supportato | Non supportato |
Totale complessivo, ad esempio GROUP BY () | Non supportato | Supportata | Supportata |
GROUPING_ID - funzione | Non supportato | Supportata | Supportata |
GROUPING - funzione | Supportata | Supportato | Supportata |
WITH CUBE | Supportata | Supportato | Supportata |
WITH ROLLUP | Supportata | Supportato | Supportata |
Rimozione di raggruppamenti duplicati relativa a WITH CUBE o WITH ROLLUP | Supportata | Supportato | Supportata |
Esempi
R. Uso di una clausola GROUP BY semplice
Nell'esempio seguente viene recuperato il totale per ogni SalesOrderID
dalla tabella SalesOrderDetail
. Questo esempio usa AdventureWorks.
SELECT SalesOrderID, SUM(LineTotal) AS SubTotal
FROM Sales.SalesOrderDetail AS sod
GROUP BY SalesOrderID
ORDER BY SalesOrderID;
B. Uso di una clausola GROUP BY con più tabelle
Nell'esempio seguente viene recuperato il numero di dipendenti per ogni City
dalla tabella Address
unita in join alla tabella EmployeeAddress
. Questo esempio usa AdventureWorks.
SELECT a.City, COUNT(bea.AddressID) EmployeeCount
FROM Person.BusinessEntityAddress AS bea
INNER JOIN Person.Address AS a
ON bea.AddressID = a.AddressID
GROUP BY a.City
ORDER BY a.City;
C. Uso di una clausola GROUP BY con un'espressione
Nell'esempio seguente vengono recuperate le vendite totali per ogni anno tramite la funzione DATEPART
. La stessa espressione deve essere presente sia nell'elenco SELECT
che nella clausola GROUP BY
.
SELECT DATEPART(yyyy,OrderDate) AS N'Year'
,SUM(TotalDue) AS N'Total Order Amount'
FROM Sales.SalesOrderHeader
GROUP BY DATEPART(yyyy,OrderDate)
ORDER BY DATEPART(yyyy,OrderDate);
D. Uso di una clausola GROUP BY con una clausola HAVING
Nell'esempio seguente viene utilizzata la clausola HAVING
per specificare quale gruppo generato nella clausola GROUP BY
deve essere incluso nel set di risultati.
SELECT DATEPART(yyyy,OrderDate) AS N'Year'
,SUM(TotalDue) AS N'Total Order Amount'
FROM Sales.SalesOrderHeader
GROUP BY DATEPART(yyyy,OrderDate)
HAVING DATEPART(yyyy,OrderDate) >= N'2003'
ORDER BY DATEPART(yyyy,OrderDate);
Esempi: Azure Synapse Analytics e Parallel Data Warehouse
E. Uso di base della clausola GROUP BY
L'esempio seguente trova l'importo totale di tutte le vendite in ogni giornata. Viene restituita una sola riga contenente il totale di tutte le vendite per ogni giornata.
-- Uses AdventureWorksDW
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales FROM FactInternetSales
GROUP BY OrderDateKey ORDER BY OrderDateKey;
F. Uso di base dell'hint DISTRIBUTED_AGG
Questo esempio usa l'hint per la query DISTRIBUTED_AGG per forzare nell'appliance la distribuzione casuale della tabella nella colonna CustomerKey
prima di eseguire l'aggregazione.
-- Uses AdventureWorksDW
SELECT CustomerKey, SUM(SalesAmount) AS sas
FROM FactInternetSales
GROUP BY CustomerKey WITH (DISTRIBUTED_AGG)
ORDER BY CustomerKey DESC;
G. Variazioni della sintassi per GROUP BY
Quando l'elenco SELECT non include aggregazioni, ogni colonna dell'elenco SELECT deve essere inclusa nell'elenco GROUP BY. Le colonne calcolate dell'elenco SELECT possono essere incluse, ma non sono richieste, nell'elenco GROUP BY. Di seguito sono riportati esempi di istruzioni SELECT sintatticamente valide:
-- Uses AdventureWorks
SELECT LastName, FirstName FROM DimCustomer GROUP BY LastName, FirstName;
SELECT NumberCarsOwned FROM DimCustomer GROUP BY YearlyIncome, NumberCarsOwned;
SELECT (SalesAmount + TaxAmt + Freight) AS TotalCost FROM FactInternetSales GROUP BY SalesAmount, TaxAmt, Freight;
SELECT SalesAmount, SalesAmount*1.10 SalesTax FROM FactInternetSales GROUP BY SalesAmount;
SELECT SalesAmount FROM FactInternetSales GROUP BY SalesAmount, SalesAmount*1.10;
H. Uso di GROUP BY con più espressioni GROUP BY
L'esempio seguente raggruppa i risultati usando più criteri GROUP BY
. Se, all'interno di ogni gruppo OrderDateKey
, sono presenti sottogruppi che possono essere differenziati da DueDateKey
, verrà definito un nuovo raggruppamento per il set di risultati.
-- Uses AdventureWorks
SELECT OrderDateKey, DueDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey, DueDateKey
ORDER BY OrderDateKey;
I. Utilizzo di una clausola GROUP BY con una clausola HAVING
L'esempio seguente usa la clausola HAVING
per specificare i gruppi generati nella clausola GROUP BY
che devono essere inclusi nel set di risultati. Nei risultati verranno inclusi solo i gruppi con date dell'ordine del 2004 o successive.
-- Uses AdventureWorks
SELECT OrderDateKey, SUM(SalesAmount) AS TotalSales
FROM FactInternetSales
GROUP BY OrderDateKey
HAVING OrderDateKey > 20040000
ORDER BY OrderDateKey;
Vedi anche
GROUPING_ID (Transact-SQL)
GROUPING (Transact-SQL)
SELECT (Transact-SQL)
SELECT Clause (Transact-SQL)