Microsoft SQL Server
RAGGRUPPA PER
Ricerca…
Raggruppamento semplice
Tabella degli ordini
Identificativo del cliente | Codice prodotto | Quantità | Prezzo |
---|---|---|---|
1 | 2 | 5 | 100 |
1 | 3 | 2 | 200 |
1 | 4 | 1 | 500 |
2 | 1 | 4 | 50 |
3 | 5 | 6 | 700 |
Quando si raggruppa per una colonna specifica, vengono restituiti solo i valori univoci di questa colonna.
SELECT customerId
FROM orders
GROUP BY customerId;
Valore di ritorno:
identificativo del cliente |
---|
1 |
2 |
3 |
Le funzioni di aggregazione come count()
applicano a ciascun gruppo e non alla tabella completa:
SELECT customerId,
COUNT(productId) as numberOfProducts,
sum(price) as totalPrice
FROM orders
GROUP BY customerId;
Valore di ritorno:
identificativo del cliente | numberOfProducts | prezzo totale |
---|---|---|
1 | 3 | 800 |
2 | 1 | 50 |
3 | 1 | 700 |
GROUP BY multiple columns
Si potrebbe desiderare GROUP BY più di una colonna
declare @temp table(age int, name varchar(15))
insert into @temp
select 18, 'matt' union all
select 21, 'matt' union all
select 21, 'matt' union all
select 18, 'luke' union all
select 18, 'luke' union all
select 21, 'luke' union all
select 18, 'luke' union all
select 21, 'luke'
SELECT Age, Name, count(1) count
FROM @temp
GROUP BY Age, Name
raggrupperà per età e nome e produrrà:
Età | Nome | contare |
---|---|---|
18 | luke | 3 |
21 | luke | 2 |
18 | opaco | 1 |
21 | opaco | 2 |
Raggruppa per più tabelle, più colonne
Raggruppa per viene spesso utilizzato con la dichiarazione di join. Supponiamo di avere due tavoli. Il primo è il tavolo degli studenti:
Id | Nome e cognome | Età |
---|---|---|
1 | Matt Jones | 20 |
2 | Frank Blue | 21 |
3 | Anthony Angel | 18 |
La seconda tabella è la tabella di discussione che ogni studente può prendere:
icLsoggetto | Soggetto |
---|---|
1 | Matematica |
2 | PE |
3 | Fisica |
E poiché uno studente può frequentare molte materie e una materia può essere frequentata da molti studenti (quindi N: N relazione), abbiamo bisogno di avere una terza tabella "delimitata". Chiamiamo la tabella Students_subjects:
icLsoggetto | student_id |
---|---|
1 | 1 |
2 | 2 |
2 | 1 |
3 | 2 |
1 | 3 |
1 | 1 |
Ora diciamo che vogliamo sapere il numero di soggetti che ogni studente sta frequentando. Qui l'istruzione GROUP BY
autonoma non è sufficiente in quanto le informazioni non sono disponibili tramite una singola tabella. Pertanto, è necessario utilizzare GROUP BY
con l'istruzione JOIN
:
Select Students.FullName, COUNT(Subject Id) as SubjectNumber FROM Students_Subjects
LEFT JOIN Students
ON Students_Subjects.Student_id = Students.Id
GROUP BY Students.FullName
Il risultato della query fornita è il seguente:
Nome e cognome | SubjectNumber |
---|---|
Matt Jones | 3 |
Frank Blue | 2 |
Anthony Angel | 1 |
Per un esempio ancora più complesso di utilizzo di GROUP BY, diciamo che lo studente potrebbe essere in grado di assegnare lo stesso oggetto al suo nome più di una volta (come mostrato nella tabella Students_Subjects). In questo scenario potremmo essere in grado di contare il numero di volte in cui ogni argomento è stato assegnato a uno studente mediante il raggruppamento di più di una colonna:
SELECT Students.FullName, Subjects.Subject,
COUNT(Students_subjects.Subject_id) AS NumberOfOrders
FROM ((Students_Subjects
INNER JOIN Students
ON Students_Subjcets.Student_id=Students.Id)
INNER JOIN Subjects
ON Students_Subjects.Subject_id=Subjects.Subject_id)
GROUP BY Fullname,Subject
Questa query fornisce il seguente risultato:
Nome e cognome | Soggetto | SubjectNumber |
---|---|---|
Matt Jones | Matematica | 2 |
Matt Jones | PE | 1 |
Frank Blue | PE | 1 |
Frank Blue | Fisica | 1 |
Anthony Angel | Matematica | 1 |
VISTA
Poiché la clausola WHERE
viene valutata prima di GROUP BY
, non è possibile utilizzare WHERE
per ridurre i risultati del raggruppamento (in genere una funzione di aggregazione, ad esempio COUNT(*)
). Per soddisfare questa esigenza, è possibile utilizzare la clausola HAVING
.
Ad esempio, utilizzando i seguenti dati:
DECLARE @orders TABLE(OrderID INT, Name NVARCHAR(100))
INSERT INTO @orders VALUES
( 1, 'Matt' ),
( 2, 'John' ),
( 3, 'Matt' ),
( 4, 'Luke' ),
( 5, 'John' ),
( 6, 'Luke' ),
( 7, 'John' ),
( 8, 'John' ),
( 9, 'Luke' ),
( 10, 'John' ),
( 11, 'Luke' )
Se vogliamo ottenere il numero di ordini che ogni persona ha piazzato, useremmo
SELECT Name, COUNT(*) AS 'Orders'
FROM @orders
GROUP BY Name
e prendi
Nome | Ordini |
---|---|
opaco | 2 |
John | 5 |
Luca | 4 |
Tuttavia, se vogliamo limitarlo a individui che hanno effettuato più di due ordini, possiamo aggiungere una clausola HAVING
.
SELECT Name, COUNT(*) AS 'Orders'
FROM @orders
GROUP BY Name
HAVING COUNT(*) > 2
cederà
Nome | Ordini |
---|---|
John | 5 |
Luca | 4 |
Si noti che, proprio come GROUP BY
, le colonne inserite in HAVING
devono corrispondere esattamente alle loro controparti SELECT
. Se nell'esempio precedente avessimo invece detto
SELECT Name, COUNT(DISTINCT OrderID)
la nostra clausola HAVING
avrebbe dovuto dire
HAVING COUNT(DISTINCT OrderID) > 2
GROUP BY con ROLLUP e CUBE
L'operatore ROLLUP è utile per generare report che contengono totali parziali e totali.
CUBE genera un set di risultati che mostra gli aggregati per tutte le combinazioni di valori nelle colonne selezionate.
ROLLUP genera un set di risultati che mostra gli aggregati per una gerarchia di valori nelle colonne selezionate.
Articolo Colore Quantità tavolo Blu 124 tavolo Rosso 223 Sedia Blu 101 Sedia Rosso 210
SELECT CASE WHEN (GROUPING(Item) = 1) THEN 'ALL'
ELSE ISNULL(Item, 'UNKNOWN')
END AS Item,
CASE WHEN (GROUPING(Color) = 1) THEN 'ALL'
ELSE ISNULL(Color, 'UNKNOWN')
END AS Color,
SUM(Quantity) AS QtySum
FROM Inventory
GROUP BY Item, Color WITH ROLLUP
Item Color QtySum
-------------------- -------------------- --------------------------
Chair Blue 101.00
Chair Red 210.00
Chair ALL 311.00
Table Blue 124.00
Table Red 223.00
Table ALL 347.00
ALL ALL 658.00
(7 righe (s) interessate)
Se la parola chiave ROLLUP nella query viene modificata in CUBE, il set di risultati CUBE è lo stesso, tranne che queste due righe aggiuntive vengono restituite alla fine:
ALL Blue 225.00
ALL Red 433.00
https://technet.microsoft.com/en-us/library/ms189305(v=sql.90).aspx