1. Introduzione all'analisi aggregata
L'operazione di aggregazione è un concetto molto importante nelle interrogazioni dei database. Viene solitamente utilizzata per l'analisi statistica, come somma, conteggio, media, valori massimi e minimi. Queste operazioni aiutano gli utenti a estrarre informazioni significative da una grande quantità di dati, fornendo supporto per l'analisi dei dati e la presa di decisioni. Le funzioni implementate nel database per l'aggregazione sono generalmente indicate come funzioni di aggregazione.
2. Operazioni di Aggregazione di Base
2.1 Concetto delle Funzioni di Aggregazione
Le funzioni di aggregazione sono funzioni utilizzate nei linguaggi di interrogazione dei database per eseguire una serie di calcoli e restituire un singolo valore. In SQL e linguaggi di interrogazione simili, le funzioni di aggregazione possono operare su una colonna di dati e restituire un singolo valore, come somma (SUM), media (AVG), conteggio (COUNT), massimo (MAX) e minimo (MIN). Quando è necessario eseguire un'analisi statistica dei dati, le funzioni di aggregazione sono strumenti importanti per l'elaborazione di set di dati ed l'estrazione di dati statistici.
2.2 Aggregazione su Singolo Campo
Nelle applicazioni pratiche, l'analisi aggregata su singolo campo è un requisito molto comune, spesso utilizzato per ottenere risultati statistici come somma, media, massimo e minimo di una colonna particolare. Supponiamo di avere una tabella di informazioni sui pagamenti e vogliamo calcolare l'importo totale pagato dagli utenti. Utilizzando il framework ent
, possiamo costruire una query dall'entità e applicare le funzioni di aggregazione come segue:
func Esegui(ctx context.Context, client *ent.Client) {
// Calcola la somma del campo Amount per l'entità Payment
somma, err := client.Payment.Query().
Aggregate(
ent.Sum(payment.Amount),
).
Int(ctx)
if err != nil {
log.Fatalf("Impossibile ottenere la somma: %v", err)
}
log.Printf("Importo totale dei pagamenti: %d", somma)
}
Nel frammento di codice sopra, avviamo una query per l'entità di pagamento utilizzando client.Payment.Query()
, quindi utilizziamo il metodo Aggregate()
per chiamare la funzione ent.Sum
con payment.Amount
come parametro per calcolare l'importo totale dei pagamenti. Usiamo .Int(ctx)
per convertire il risultato dell'aggregazione in un intero e lo registriamo.
2.3 Aggregazione su Più Campi
In molti casi, è necessario eseguire operazioni di aggregazione su più campi anziché uno solo. In questa sezione, illustreremo come ottenere un'aggregazione su più campi attraverso un esempio.
In questo esempio, sommeremo, troveremo il minimo, il massimo e conteremo il campo Age
nella tabella dei pet.
func Esegui(ctx context.Context, client *ent.Client) {
var v []struct {
Somma, Minimo, Massimo, Conteggio int
}
err := client.Pet.Query().
Aggregate(
ent.Sum(pet.FieldAge), // Somma di Age
ent.Min(pet.FieldAge), // Età minima
ent.Max(pet.FieldAge), // Età massima
ent.Count(), // Conteggio
).
Scan(ctx, &v)
if err != nil {
log.Fatalf("Interrogazione fallita: %v", err)
}
// Output di tutti i risultati dell'aggregazione
for _, agg := range v {
fmt.Printf("Somma: %d Minimo: %d Massimo: %d Conteggio: %d\n", agg.Somma, agg.Minimo, agg.Massimo, agg.Conteggio)
}
}
Nel codice sopra, utilizziamo la funzione Aggregate
per eseguire un'aggregazione su più campi, e utilizziamo la funzione Scan
per memorizzare i risultati dell'aggregazione nella slice v
. Quindi, iteriamo attraverso v
per visualizzare tutti i risultati dell'aggregazione.
3. Applicazione dell'Aggregazione con Group By
3.1 Utilizzo di Group By per Raggruppare i Campi
Nelle operazioni dei database, Group By
è un metodo comune per raggruppare i dati. In questa sezione, impareremo come utilizzare Group By
per raggruppare i dati nel database.
Esempio di tutorial, come raggruppare uno o più campi utilizzando Group By.
Supponiamo di avere una tabella utenti e dobbiamo raggruppare il campo nome
degli utenti e calcolare il numero di utenti in ciascun gruppo. Di seguito è riportato un esempio di codice su come soddisfare questo requisito:
func Esegui(ctx context.Context, client *ent.Client) {
nomi, err := client.User.
Query().
GroupBy(user.FieldName).
Strings(ctx)
if err != nil {
log.Fatalf("Impossibile eseguire la query raggruppata: %v", err)
}
// Stampare il nome di ciascun gruppo
for _, nome := range nomi {
fmt.Println("Nome gruppo:", nome)
}
}
Nel codice sopra, utilizziamo il metodo GroupBy
del costruttore di query per specificare quale campo vogliamo raggruppare.
3.2. Raggruppamento e aggregazione di più campi
A volte, desideriamo raggruppare i dati basati su più campi e eseguire funzioni di aggregazione su ciascun gruppo. Di seguito è riportato un esempio su come soddisfare tale requisito:
Il codice seguente illustra come raggruppare i dati nella tabella degli utenti in base ai campi name
e age
e calcolare l'età totale e il numero di utenti in ciascun gruppo.
func Esegui(ctx context.Context, client *ent.Client) {
var v []struct {
Name string `json:"name"`
Age int `json:"age"`
Sum int `json:"sum"`
Count int `json:"count"`
}
err := client.User.Query().
GroupBy(user.FieldName, user.FieldAge).
Aggregate(ent.Count(), ent.Sum(user.FieldAge)).
Scan(ctx, &v)
if err != nil {
log.Fatalf("Impossibile eseguire la query di raggruppamento e aggregazione su più campi: %v", err)
}
// Output delle informazioni dettagliate per ciascun gruppo
for _, group := range v {
fmt.Printf("Nome: %s Età: %d Somma: %d Conteggio: %d\n", group.Name, group.Age, group.Sum, group.Count)
}
}
In questo esempio, non solo raggruppiamo i dati basandoci sui campi name
e age
nella tabella degli utenti, ma utilizziamo anche le funzioni di aggregazione Count
e Sum
per calcolare il numero totale di record e l'età totale in ciascun gruppo.
4. Combinare Having con Group By
La clausola Having
filtra i risultati aggregati ottenuti dopo l'operazione Group By
. L'esempio seguente mostra come selezionare solo gli utenti con l'età massima in ciascun ruolo:
func Esegui(ctx context.Context, client *ent.Client) {
var users []struct {
Id Int
Age Int
Role string
}
err := client.User.Query().
Modify(func(s *sql.Selector) {
s.GroupBy(user.FieldRole)
s.Having(
sql.EQ(
user.FieldAge,
sql.Raw(sql.Max(user.FieldAge)),
),
)
}).
ScanX(ctx, &users)
if err != nil {
log.Fatalf("Impossibile eseguire la query di combinazione di Having con Group By: %v", err)
}
// Output delle informazioni dell'utente che soddisfano la condizione di Having
for _, user := range users {
fmt.Printf("ID: %d Età: %d Ruolo: %s\n", user.Id, user.Age, user.Role)
}
}
Il codice sopra genererà una query SQL equivalente per selezionare gli utenti con l'età massima in ciascun ruolo.