1. Introduction à l'analyse des agrégats
L'opération d'agrégation est un concept très important dans les requêtes de base de données. Elle est généralement utilisée pour l'analyse statistique telle que la somme, le comptage, la moyenne, les valeurs maximales et minimales. Ces opérations aident les utilisateurs à extraire des informations significatives à partir d'une grande quantité de données, fournissant un support pour l'analyse des données et la prise de décision. Les fonctions mises en œuvre dans la base de données pour l'agrégation sont généralement appelées fonctions d'agrégat.
2. Opérations d'agrégation de base
2.1 Concept des fonctions d'agrégat
Les fonctions d'agrégat sont des fonctions utilisées dans les langages de requêtes de base de données pour effectuer une série de calculs et renvoyer une seule valeur. En SQL et dans des langages de requête similaires, les fonctions d'agrégat peuvent opérer sur une colonne de données et renvoyer une seule valeur, telles que la somme (SUM), la moyenne (AVG), le comptage (COUNT), le maximum (MAX) et le minimum (MIN). Lorsque nous avons besoin d'effectuer une analyse statistique des données, les fonctions d'agrégat sont des outils importants pour le traitement des ensembles de données et l'extraction de données statistiques.
2.2 Agrégation sur un seul champ
Dans les applications pratiques, l'analyse d'agrégation sur un seul champ est une exigence très courante, souvent utilisée pour obtenir des résultats statistiques tels que la somme, la moyenne, les valeurs maximales et minimales d'une colonne particulière. Supposons que nous ayons une table d'informations de paiement et que nous voulions calculer le montant total payé par les utilisateurs. En utilisant le framework ent
, nous pouvons construire une requête à partir de l'entité et appliquer des fonctions d'agrégat comme suit :
func Do(ctx context.Context, client *ent.Client) {
// Calculer la somme du champ Montant pour l'entité de Paiement
sum, err := client.Payment.Query().
Aggregate(
ent.Sum(payment.Amount),
).
Int(ctx)
if err != nil {
log.Fatalf("Échec de l'obtention de la somme : %v", err)
}
log.Printf("Montant total des paiements : %d", sum)
}
Dans l'extrait de code ci-dessus, nous initions une requête pour l'entité de paiement en utilisant client.Payment.Query()
, puis utilisons la méthode Aggregate()
pour appeler la fonction ent.Sum
avec payment.Amount
comme paramètre pour calculer le montant total des paiements. Nous utilisons .Int(ctx)
pour convertir le résultat agrégé en entier et le consigner.
2.3 Agrégation sur plusieurs champs
Dans de nombreux cas, nous devons effectuer des opérations d'agrégation sur plusieurs champs plutôt que sur un seul. Dans cette section, nous allons démontrer comment atteindre une agrégation sur plusieurs champs à travers un exemple.
Dans cet exemple, nous allons additionner, trouver le minimum, trouver le maximum et compter le champ Âge
dans la table des animaux.
func Do(ctx context.Context, client *ent.Client) {
var v []struct {
Sum, Min, Max, Count int
}
err := client.Pet.Query().
Aggregate(
ent.Sum(pet.FieldAge), // Somme de l'Âge
ent.Min(pet.FieldAge), // Âge minimum
ent.Max(pet.FieldAge), // Âge maximum
ent.Count(), // Compter
).
Scan(ctx, &v)
if err != nil {
log.Fatalf("Échec de la requête : %v", err)
}
// Afficher tous les résultats agrégés
for _, agg := range v {
fmt.Printf("Somme : %d Min : %d Max : %d Count : %d\n", agg.Sum, agg.Min, agg.Max, agg.Count)
}
}
Dans le code ci-dessus, nous utilisons la fonction Aggregate
pour effectuer une agrégation sur plusieurs champs, et utilisons la fonction Scan
pour stocker les résultats de l'agrégation dans la tranche v
. Ensuite, nous itérons à travers v
pour afficher tous les résultats agrégés.
3. Application de l'agrégation Group By
3.1. Utilisation de Group By pour regrouper des champs
Dans les opérations de base de données, Group By
est une méthode courante pour regrouper des données. Dans cette section, nous allons apprendre comment utiliser Group By
pour regrouper des données dans la base de données.
Exemple tutoriel, comment regrouper un ou plusieurs champs en utilisant Group By.
En supposant que nous ayons une table d'utilisateurs et que nous devions regrouper le champ name
des utilisateurs et calculer le nombre d'utilisateurs dans chaque groupe. Voici un exemple de code pour atteindre cette exigence :
func Do(ctx context.Context, client *ent.Client) {
names, err := client.User.
Query().
GroupBy(user.FieldName).
Strings(ctx)
if err != nil {
log.Fatalf("Échec de l'exécution de la requête groupée : %v", err)
}
// Afficher le nom de chaque groupe
for _, name := range names {
fmt.Println("Nom du groupe :", name)
}
}
Dans le code ci-dessus, nous utilisons la méthode GroupBy
du générateur de requêtes pour spécifier quel champ nous voulons regrouper par.
3.2. Regroupement et Agrégation de Plusieurs Champs
Parfois, nous voulons regrouper des données en fonction de plusieurs champs et effectuer des fonctions d'agrégation sur chaque groupe. Voici un exemple de la manière d'atteindre cette exigence :
Le code suivant montre comment regrouper les données dans la table utilisateur en fonction des champs nom
et âge
, et calculer l'âge total et le nombre d'utilisateurs dans chaque groupe.
func Do(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("Échec de l'exécution de la requête de regroupement et d'agrégation sur plusieurs champs : %v", err)
}
// Afficher les informations détaillées pour chaque groupe
for _, group := range v {
fmt.Printf("Nom: %s Âge: %d Somme: %d Nombre: %d\n", group.Name, group.Age, group.Sum, group.Count)
}
}
Dans cet exemple, nous regroupons non seulement les données en fonction des champs nom
et âge
dans la table utilisateur, mais nous utilisons également les fonctions d'agrégation Count
et Sum
pour calculer le nombre total d'enregistrements et l'âge total dans chaque groupe.
4. Combinaison de Having avec Group By
La clause Having
filtre les résultats d'agrégation obtenus après l'opération Group By
. L'exemple suivant montre comment sélectionner uniquement les utilisateurs ayant l'âge maximal dans chaque rôle :
func Do(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("Échec de l'exécution de la requête Having combinée avec Group By : %v", err)
}
// Afficher les informations utilisateur satisfaisant la condition Having
for _, user := range users {
fmt.Printf("ID: %d Âge: %d Rôle: %s\n", user.Id, user.Age, user.Role)
}
}
Le code ci-dessus générera une requête SQL équivalente pour sélectionner les utilisateurs ayant l'âge maximal dans chaque rôle.