- Apprendre
- Informatique et numérique
- Programmation
- SQL : requêtes SELECT, jointures et agrégation
- Fonctions d’agrégation SQL
Fonctions d’agrégation SQL et GROUP BY
DébutantUnité 4 sur 6 de la formation Formation : SQL : requêtes SELECT, jointures et agrégation
Ce que tu vas apprendre
- Utiliser COUNT, SUM, AVG, MIN et MAX pour obtenir des valeurs de synthèse à partir de nombreuses lignes, choisir le type de comptage adapté et prévoir comment les valeurs manquantes modifient un résultat.
- Calculer des totaux, des moyennes, des minimums et des maximumsUtiliser SUM, AVG, MIN et MAX sur une table entière ou sur les lignes conservées par une clause WHERE, et combiner plusieurs de ces fonctions dans une même requête.
- Compter les lignes, les valeurs et les valeurs distinctesChoisir entre COUNT(*), COUNT(column) et COUNT(DISTINCT column), et savoir comment chacun traite les valeurs répétées et manquantes.
- Prévoir l’effet des valeurs NULL sur les agrégatsSavoir que les agrégats ignorent les valeurs NULL, prévoir les résultats pour des entrées vides et remplacer NULL par une valeur par défaut lorsque la question le demande.
- Calculer des totaux, des moyennes, des minimums et des maximums
- Utiliser GROUP BY pour obtenir une ligne de synthèse par catégorie, par combinaison de valeurs ou par valeur calculée, et respecter la règle sur ce qu’une requête groupée peut afficher.
- Synthétiser chaque catégorie avec GROUP BYRépartir une table en groupes qui partagent une valeur, calculer des agrégats par groupe, puis trier et limiter le résultat groupé.
- Respecter la règle sur ce qu’une requête groupée peut afficherSavoir quelles colonnes peuvent figurer dans la liste SELECT d’une requête groupée, corriger l’erreur produite lorsque la règle n’est pas respectée et reconnaître les différences entre bases de données.
- Regrouper selon plusieurs colonnes et selon des valeurs calculéesRegrouper les lignes selon des combinaisons de colonnes et des expressions comme le mois d’une date ou une catégorie CASE, et lire le résultat plus détaillé.
- Synthétiser chaque catégorie avec GROUP BY
- Conserver uniquement les groupes dont les totaux, les effectifs ou les moyennes remplissent une condition, et décider si une condition relève de WHERE ou de HAVING.
- Conserver les groupes qui remplissent une conditionÉcrire des conditions HAVING sur des valeurs agrégées, y compris des agrégats qui ne sont pas affichés, pour filtrer un résultat groupé.
- Choisir entre WHERE et HAVINGUtiliser l’ordre logique d’une requête pour déterminer si une condition filtre des lignes ou des groupes, et prévoir comment ce choix modifie le résultat.
- Conserver les groupes qui remplissent une condition
- Éviter la division entière, connaître le type de nombre renvoyé par chaque agrégat et arrondir les moyennes, les totaux et les pourcentages au bon moment.
- Éviter la division entière dans les moyennes et les pourcentagesReconnaître quand la division d’agrégats fait perdre les décimales, corriger le problème avec un opérande décimal et connaître les différences de types de résultat entre bases de données.
- Arrondir des résultats agrégésArrondir les moyennes, les totaux et les pourcentages avec ROUND, arrondir au bon moment et gérer les différences entre SQLite et PostgreSQL.
- Éviter la division entière dans les moyennes et les pourcentages
- Combiner CASE avec des agrégats pour obtenir des comptages, des sommes et des pourcentages conditionnels, et traduire une question en une requête groupée dont tu peux vérifier les chiffres.
- Compter et additionner selon une condition avec CASEPlacer une expression CASE dans un agrégat pour calculer plusieurs comptages, sommes et pourcentages conditionnels dans une même requête groupée.
- Construire et vérifier une requête de synthèse à partir d’une questionTraduire une question métier en une requête groupée étape par étape, éviter de mélanger les niveaux de détail et vérifier l’exactitude des chiffres.
- Compter et additionner selon une condition avec CASE
Fonctions d’agrégation SQL : cours
1Synthétiser des données avec les fonctions d’agrégation
Une table enregistre des événements individuels ; un rapport a souvent besoin de quelques nombres qui les décrivent ensemble. Les fonctions d’agrégation transforment les lignes en effectifs, totaux, moyennes et valeurs extrêmes. Choisir la fonction n’est qu’une partie du travail : tu dois aussi déterminer quelles lignes entrent dans le calcul et ce que signifient les valeurs manquantes. Nous utiliserons une petite table de commandes pour vérifier chaque réponse à la main avant de nous fier à la requête.
1.1 Calculer des totaux, des moyennes, des minimums et des maximums
Une fonction d’agrégation combine les valeurs de plusieurs lignes en un seul résultat. Oracle l’appelle aussi fonction de groupe. Sans GROUP BY, une requête d’agrégation traite toutes les lignes qui satisfont WHERE comme un seul groupe et renvoie une ligne de synthèse.
Partir de données vérifiables
Chaque ligne de orders représente une commande. Les colonnes de nombres ci-dessous contiennent des entiers ; order_id est la clé primaire. Les dates sont au format texte ISO dans SQLite et de type DATE dans PostgreSQL.
| order_id | customer | region | amount | quantity | discount | order_date |
|---|---|---|---|---|---|---|
| 1 | Ana | East | 120 | 2 | 10 | 2026-01-05 |
| 2 | Ben | West | 80 | 1 | NULL | 2026-01-17 |
| 3 | Ana | East | 45 | 3 | 5 | 2026-02-02 |
| 4 | Chen | North | 200 | 4 | NULL | 2026-02-14 |
| 5 | Ben | West | 60 | 1 | 0 | 2026-02-20 |
| 6 | Dara | East | 95 | 2 | NULL | 2026-03-03 |
| 7 | Chen | North | 150 | 5 | 15 | 2026-03-09 |
| 8 | Eli | NULL | 30 | 1 | NULL | 2026-03-21 |
Choisir la mesure
SUM(amount) additionne les montants. AVG(amount) donne leur moyenne arithmétique. MIN(amount) trouve le plus petit montant et MAX(amount) le plus grand. Tu peux demander les quatre dans une seule requête :
SELECT SUM(amount) AS total, AVG(amount) AS avg_amount, MIN(amount) AS smallest, MAX(amount) AS largest FROM orders;
Le résultat est une ligne : total 780, moyenne 97,5, minimum 30 et maximum 200. Additionne les huit montants pour obtenir 780, puis divise par huit pour obtenir 97,5. Chaque fonction utilise les mêmes huit lignes en entrée. Des alias clairs après AS rendent les en-têtes du résultat utiles ; un en-tête généré comme sum indique peu de chose sur ce qui a été additionné.
Filtrer avant de calculer
Pour synthétiser les commandes de East, écris SELECT COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE region = 'East';. Le filtre conserve les montants 120, 45 et 95. La requête renvoie trois commandes et un total de 260. WHERE choisit les lignes en entrée avant l’exécution de tout agrégat.
Un agrégat peut aussi prendre une expression calculée. Dans une table contenant quantity et unit_price, SUM(quantity * unit_price) calcule d’abord le chiffre d’affaires de chaque ligne, puis additionne ces chiffres d’affaires. Deux lignes, l’une de deux articles à 5 et l’autre de trois articles à 10, contribuent pour 10 et 30, soit un total de 40. SUM(quantity) * SUM(unit_price) multiplie quant à lui 5 par 15 et donne 75. Placer le calcul dans SUM conserve le prix correspondant à chaque quantité.
Interpréter correctement les valeurs extrêmes
MIN(order_date) vaut 2026-01-05 et MAX(order_date) vaut 2026-03-21. Les valeurs de date et les dates au format texte ISO se trient chronologiquement. Un texte tel que '03/21/2026' suit l’ordre des caractères, qui ne correspond pas toujours à l’ordre des dates. Les valeurs textuelles extrêmes suivent aussi la collation de la base de données, c’est-à-dire ses règles de comparaison du texte. Ici, les clients aux extrémités sont 'Ana' et 'Eli' ; un mélange de majuscules et de minuscules peut modifier l’ordre du texte.
MAX(amount) renvoie un montant, et non la commande entière qui le contient. Pour afficher un client ayant passé une commande du montant le plus élevé, utilise SELECT customer, amount FROM orders ORDER BY amount DESC LIMIT 1;. PostgreSQL rejette une colonne simple customer à côté de MAX(amount) sans regroupement approprié. SQLite possède une règle particulière pour un seul MIN ou MAX qui peut renvoyer une colonne voisine de la ligne contenant la valeur extrême, mais les valeurs extrêmes ex aequo nécessitent toujours une règle de départage.
Points clés
- Un agrégat renvoie une valeur pour un ensemble de lignes.
WHEREsélectionne les lignes utilisées par l’agrégat.- Calcule la contribution de chaque ligne dans
SUMlorsque les valeurs doivent rester associées. MINetMAXsuivent l’ordre des nombres, des dates ou du texte.- Une valeur extrême ne permet pas d’identifier une ligne entière.
1.2 Compter les lignes, les valeurs et les valeurs distinctes
« Combien ? » peut porter sur les lignes, les valeurs enregistrées ou les valeurs différentes. Ce sont des comptages différents, même lorsqu’ils donnent par hasard le même nombre dans une petite table.
Trois formes de COUNT
| Expression | Ce qu’elle compte |
|---|---|
COUNT(*) | Toutes les lignes en entrée |
COUNT(region) | Les lignes dont la région n’est pas NULL |
COUNT(DISTINCT region) | Les différentes valeurs de région non NULL |
Dans la table des commandes, les régions sont East, West, East, North, West, East, North et NULL. SELECT COUNT(*) AS order_rows, COUNT(region) AS with_region, COUNT(DISTINCT region) AS regions FROM orders; renvoie 8, 7 et 3. Les noms de région répétés sont comptés séparément par COUNT(region), mais chaque nom ne contribue qu’une fois au comptage des valeurs distinctes.
Pour répondre à « Combien de clients différents ont commandé ? », utilise COUNT(DISTINCT customer). Ana, Ben et Chen apparaissent chacun deux fois, tandis que Dara et Eli apparaissent une fois : la réponse est donc cinq clients. COUNT(customer) renvoie huit, car chaque commande indique un client. Ce comptage mesure les lignes de commande qui nomment un client, et non les personnes.
Un zéro enregistré compte aussi
Les remises sont 10, NULL, 5, NULL, 0, NULL, 15 et NULL. COUNT(discount) renvoie quatre. Le zéro indique une valeur connue et compte comme 10, 5 et 15. Une chaîne vide est aussi une valeur dans SQLite et PostgreSQL ; Oracle traite une chaîne vide comme NULL.
Soustrais le nombre de valeurs non NULL du nombre de lignes pour mesurer les données manquantes : SELECT COUNT(*) - COUNT(region) AS missing_region FROM orders; renvoie un. Cela fonctionne parce que les deux comptages utilisent exactement les mêmes lignes en entrée.
Listes distinctes et comptages distincts
SELECT DISTINCT region FROM orders; liste East, West, North et une ligne NULL. Son rôle est de renvoyer les différentes valeurs, et NULL reste dans cette liste. COUNT(DISTINCT region) renvoie trois, car le comptage ignore NULL. Ne déduis pas un nombre de valeurs distinctes en comptant une liste sans avoir décidé si sa ligne NULL doit être incluse.
DISTINCT peut aussi figurer dans SUM ou AVG. Les quantités sont 2, 1, 3, 4, 1, 2, 5 et 1. Leur somme ordinaire est de 19. SUM(DISTINCT quantity) ne conserve que 1, 2, 3, 4 et 5, ce qui donne 15. Les quantités répétées correspondent généralement à de véritables ventes supplémentaires. Les supprimer change la mesure ; cela ne corrige pas des enregistrements en double.
Compter les combinaisons en deux étapes
Pour obtenir les paires région-client différentes, crée d’abord une liste distincte :
SELECT COUNT(*) FROM (SELECT DISTINCT region, customer FROM orders) AS pairs;
La requête interne renvoie cinq paires : East/Ana, East/Dara, North/Chen, West/Ben et NULL/Eli. Le COUNT(*) externe compte ces cinq lignes, y compris NULL/Eli. Cette forme fonctionne dans SQLite et PostgreSQL. MySQL accepte aussi COUNT(DISTINCT region, customer), mais cette forme exclut les combinaisons contenant NULL et peut donc répondre à une autre question. Dans SQLite et PostgreSQL, la forme avec des éléments séparés par une virgule est invalide.
Enfin, un comptage ne renvoie jamais NULL. SELECT COUNT(*) FROM orders WHERE region = 'South'; renvoie une ligne de synthèse contenant zéro, car aucune commande ne correspond.
Points clés
- Choisis entre les lignes, les valeurs enregistrées et les valeurs enregistrées différentes.
- Zéro est une valeur enregistrée :
COUNT(column)l’inclut donc. - Une liste distincte peut inclure NULL ;
COUNT(DISTINCT column)l’ignore. SUM(DISTINCT x)supprime les valeurs répétées, y compris les répétitions légitimes.- Compte les combinaisons distinctes en comptant les lignes d’un résultat interne distinct.
COUNTrenvoie zéro pour une entrée vide.
1.3 Prévoir l’effet des valeurs NULL sur les agrégats
NULL signifie qu’une valeur est manquante ou inconnue. Il modifie les valeurs reçues par un agrégat : un total ou une moyenne peut donc être valide en SQL tout en mesurant autre chose que ce que tu voulais.
Déterminer le dénominateur
Supposons que scores contienne Ana 80, Ben NULL, Chen 70 et Dara 90. SUM(score) vaut 240, COUNT(score) vaut trois et COUNT(*) vaut quatre. AVG(score) vaut 80 : les trois scores enregistrés totalisent 240 et sont divisés par trois.
Les cinq agrégats standard ignorent les arguments NULL. COUNT(*) compte toutes les lignes parce qu’il n’évalue pas d’argument de colonne. MIN(score) vaut 70 et MAX(score) vaut 90 ; NULL ne devient ni le plus petit ni le plus grand score. C’est différent du tri, où les valeurs NULL occupent une extrémité du résultat : en premier dans un tri croissant sous SQLite, en dernier dans un tri croissant sous PostgreSQL.
Une moyenne calculée à la main nécessite le nombre de valeurs non NULL : 1.0 * SUM(score) / NULLIF(COUNT(score), 0). L’opérande décimal conserve les résultats fractionnaires et NULLIF transforme un diviseur nul en NULL. Une division par COUNT(*) donnerait 60 et traiterait en pratique le score manquant comme un zéro.
Déterminer le sens d’une valeur par défaut
COALESCE renvoie son premier argument non NULL. Si Ben n’a pas été noté, laisse le score manquant et calcule la moyenne des résultats connus. Si un examen manqué est enregistré comme NULL mais doit compter pour zéro, AVG(COALESCE(score, 0)) calcule la moyenne de 80, 0, 70 et 90, soit 60. Le sens des données détermine si ce remplacement est justifié.
Compare le placement de COALESCE à l’intérieur et à l’extérieur d’une fonction. AVG(COALESCE(score, 0)) modifie les valeurs utilisées pour la moyenne. COALESCE(AVG(score), 0) modifie uniquement un résultat final NULL ; pour ces scores, il donne toujours 80. NVL(x, 0) dans Oracle est une autre forme à deux arguments pour remplacer NULL.
Distinguer l’absence de lignes de l’absence de valeurs enregistrées
Avec WHERE region = 'South', aucune commande ne reste. Une requête d’agrégation sans GROUP BY renvoie tout de même une ligne : COUNT(*) vaut zéro, tandis que SUM(amount), AVG(amount), MIN(amount) et MAX(amount) valent NULL. Pour afficher un total vide sous la forme zéro, utilise COALESCE(SUM(amount), 0). SQLite propose aussi TOTAL(amount), qui renvoie 0.0 pour une entrée vide.
Conserve maintenant les quatre commandes dont la remise est NULL. Il y a des lignes, mais aucune valeur de remise enregistrée : COUNT(*) vaut quatre, COUNT(discount) vaut zéro et SUM(discount) vaut NULL. Zéro valeur enregistrée et quatre valeurs manquantes sont deux constats différents.
Vérifier les expressions avant leur entrée dans SUM
Un calcul arithmétique avec NULL produit NULL. Dans SUM(amount - discount), les quatre commandes sans remise enregistrée n’apportent aucune valeur. Seules les lignes dont la remise est connue contribuent : 110, 40, 60 et 135, soit un total de 345.
Si une remise manquante signifie qu’il n’y a pas de remise, écris SUM(amount - COALESCE(discount, 0)). Chaque commande contribue alors au résultat ; le montant total de 780 moins les remises enregistrées de 30 donne 750. Entourer la somme entière de COALESCE ne rétablirait pas les commandes omises, car 345 n’est déjà pas NULL.
Pour repérer les valeurs manquantes, utilise IS NULL ou IS NOT NULL. WHERE discount IS NULL trouve quatre commandes. discount = NULL n’est jamais vrai et ne peut donc pas les sélectionner.
Points clés
AVG(x)divise par le nombre de valeurs non NULL.- Un
COALESCEintérieur modifie les entrées ; s’il est placé à l’extérieur, il modifie un résultat NULL. - Une entrée vide donne zéro pour
COUNTet NULL pour les quatre autres agrégats. - NULL dans une expression arithmétique peut supprimer la contribution d’une ligne.
2Regrouper des lignes et synthétiser chaque groupe
Un total sur toute la table répond à une question, mais de nombreux rapports demandent un résultat par client, par région ou par mois. Le regroupement fixe ce niveau de détail avant l’exécution des agrégats. Tu suivras la formation des groupes à partir des lignes, choisiras des colonnes capables de décrire un groupe entier et verras comment l’ajout d’une colonne de regroupement modifie le rapport. Le tri détermine ensuite la présentation des résultats ; le regroupement seul ne leur donne pas d’ordre.
2.1 Synthétiser chaque catégorie avec GROUP BY
GROUP BY rassemble les lignes qui partagent une valeur de regroupement. Chaque agrégat s’exécute séparément dans chaque groupe et le résultat contient une ligne pour chaque groupe existant après filtrage.
Déterminer ce que signifie une ligne de résultat
« Total des ventes par région » demande une ligne de résultat par région. Commence par écrire cette phrase, puis utilise region comme colonne de regroupement :
SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region;
Les trois montants de East, 120, 45 et 95, forment un groupe. Son effectif est de trois et son total de 260. North compte deux commandes pour un total de 350 ; West en compte deux pour un total de 140. La commande d’Eli forme un groupe de région NULL avec une commande d’un total de 30. Il y a quatre lignes de résultat, et non huit.
Lis la requête comme une succession d’étapes : FROM fournit les commandes, un éventuel WHERE retire des lignes, GROUP BY rassemble les lignes restantes par région et les agrégats synthétisent chaque ensemble. SELECT affiche son libellé et ses mesures. Le regroupement n’élimine pas les petites commandes d’un groupe ; elles contribuent toutes au résultat, sauf si un filtre sur les lignes les a retirées.
Garder les catégories manquantes visibles
Les lignes dont la colonne de regroupement vaut NULL appartiennent à un seul groupe NULL. C’est utile : un rapport peut montrer l’importance de l’activité sans région enregistrée. Il ne traite pas chaque région manquante comme une catégorie différente.
Pour afficher un libellé lisible, sélectionne COALESCE(region, 'No region') AS region_label et conserve GROUP BY region. Le libellé modifie la valeur affichée. Pour exclure ces lignes des calculs, ajoute WHERE region IS NOT NULL avant GROUP BY. Les totaux obtenus ont une somme de 750, car le montant de 30 d’Eli a été exclu.
Une requête groupée sur une entrée sans lignes ne renvoie aucun groupe. Par exemple, filtrer la table sur South puis regrouper par région ne renvoie aucune ligne de résultat. C’est différent d’un agrégat sur toute la table sans GROUP BY, qui produit une ligne de synthèse même lorsque l’entrée est vide.
Trier explicitement les groupes
GROUP BY ne garantit aucun ordre de sortie. Pour lister d’abord les régions aux totaux les plus élevés, ajoute ORDER BY total DESC. L’alias total est autorisé dans ORDER BY ; ORDER BY SUM(amount) DESC produit le même tri.
Un rapport par client peut sélectionner les trois premiers totaux :
SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer ORDER BY total DESC, customer LIMIT 3;
Il renvoie Chen 350, Ana 165 et Ben 140. La seconde clé de tri, customer, donne un ordre reproductible aux totaux ex aequo. LIMIT 3 ne renvoie que trois lignes ; il ne conserve pas tous les ex aequo à la limite. SQL Server exprime cette limite avec SELECT TOP 3, tandis qu’Oracle prend en charge FETCH FIRST 3 ROWS ONLY.
Lors d’un tri croissant des libellés de catégorie, SQLite place normalement NULL en premier et PostgreSQL en dernier. Précise l’ordre voulu lorsque cette position compte.
Vérifier la colonne de regroupement
SELECT DISTINCT region FROM orders et SELECT region FROM orders GROUP BY region renvoient les mêmes libellés de région distincts, y compris NULL. Utilise le regroupement lorsque tu as aussi besoin d’une mesure pour chaque libellé.
Un regroupement selon order_id, qui est unique, donne huit groupes d’une ligne chacun. Chaque effectif vaut un et chaque total de montant est égal au montant initial. Pour un rapport régional, ce résultat indique que la colonne de regroupement est trop détaillée.
Points clés
- Précise ce que représente une ligne de résultat avant de choisir
GROUP BY. - Toutes les valeurs de regroupement NULL forment un seul groupe.
- Utilise
ORDER BYpour fixer l’ordre du résultat et une seconde clé pour départager les ex aequo. - Un regroupement par clé de ligne unique produit des groupes d’une ligne.
2.2 Respecter la règle sur ce qu’une requête groupée peut afficher
Un rapport groupé doit faire tenir plusieurs lignes en entrée dans une seule ligne de résultat. Chaque valeur affichée doit donc avoir un sens clair pour l’ensemble du groupe. C’est pourquoi SQL limite les colonnes que tu peux sélectionner.
Respecter la règle de regroupement portable
Un élément d’un SELECT groupé doit être une colonne de regroupement, une expression construite à partir de colonnes de regroupement, un agrégat ou une constante. Considère cette requête :
SELECT region, customer, COUNT(*) FROM orders GROUP BY region;
East contient Ana, Ana et Dara. Le groupe a une seule région et un seul effectif, mais deux noms de clients différents. La requête n’indique pas quel client afficher dans l’unique résultat pour East. PostgreSQL rejette la colonne customer non regroupée.
Le même problème se pose sans GROUP BY : SELECT customer, SUM(amount) FROM orders associe un total sur toute la table à un nom individuel. Le total n’a pas un seul client pour le désigner.
Corriger la requête selon la question
Il existe trois corrections utiles, chacune ayant un sens différent :
- Pour obtenir une ligne par région, retire
customer:SELECT region, COUNT(*) FROM orders GROUP BY region;. - Pour obtenir une ligne par région et par client, regroupe selon les deux :
SELECT region, customer, COUNT(*) FROM orders GROUP BY region, customer;. - Pour obtenir le nombre de clients par région, agrège les noms :
SELECT region, COUNT(DISTINCT customer) AS customers FROM orders GROUP BY region;.
La dernière requête indique deux clients dans East et un dans chacun des autres groupes de régions. Ajouter une colonne à GROUP BY peut modifier le niveau de détail du rapport : choisis donc la correction en fonction de la question, et pas seulement du message d’erreur.
Une colonne de regroupement peut être omise de SELECT. SELECT COUNT(*) FROM orders GROUP BY region; est valide et renvoie quatre effectifs : trois, deux, deux et un, sans ordre garanti. Ces nombres sont difficiles à utiliser sans leurs libellés de région.
Appliquer la règle au-delà de SELECT
Un ORDER BY customer groupé pose le même problème lorsqu’on regroupe uniquement par région : quel client doit déterminer la place de East ? Les conditions HAVING d’une requête groupée doivent aussi décrire un groupe entier. Utilise-y des colonnes de regroupement ou des expressions d’agrégation.
Reconnaître le comportement permissif d’une base de données
SQLite accepte une colonne nue, c’est-à-dire une colonne sélectionnée qui n’est ni regroupée ni agrégée. Il prend une valeur dans une ligne en entrée du groupe. Un résultat apparemment correct comme 'Ana' à côté de East ne signifie pas qu’Ana représente toutes les commandes de cette région.
Avec exactement un agrégat MIN ou MAX intégré, SQLite prend les valeurs des colonnes nues dans une ligne contenant la valeur extrême. Les ex aequo et la présence de plusieurs agrégats de valeurs extrêmes rendent incertaine la ligne choisie. Ce raccourci est propre à la base de données. Trier les lignes initiales est plus clair lorsque tu cherches une commande dont le montant est extrême.
Le mode ONLY_FULL_GROUP_BY activé par défaut dans MySQL rejette les valeurs non regroupées qui ne sont pas déterminées par le groupe. ANY_VALUE(customer) autorise explicitement une valeur arbitraire, mais ne trouve pas le client associé à un total choisi. SQL Server et Oracle rejettent aussi les colonnes ordinaires non regroupées.
PostgreSQL et MySQL reconnaissent une exception pour la clé primaire : regrouper selon la clé primaire d’une table identifie une seule ligne, ce qui détermine ses autres colonnes. SELECT order_id, customer, SUM(amount) FROM orders GROUP BY order_id fonctionne dans PostgreSQL. Énumérer chaque colonne simple affichée dans GROUP BY reste la méthode portable.
Points clés
- Chaque valeur affichée doit décrire l’ensemble du groupe.
- Retirer, regrouper ou agréger une colonne répond à des questions différentes.
- La règle de regroupement s’applique aussi à
HAVINGet àORDER BYdans une requête groupée. - Les colonnes nues acceptées par SQLite peuvent masquer un rapport incorrect.
- Une clé primaire utilisée pour le regroupement détermine les autres colonnes de sa ligne.
2.3 Regrouper selon plusieurs colonnes et selon des valeurs calculées
Certains rapports nécessitent une combinaison de catégories ou une catégorie calculée à partir de chaque ligne. SQL peut regrouper selon plusieurs colonnes ou selon une expression. Le choix essentiel reste ce que représente une ligne de résultat.
Regrouper selon une combinaison
GROUP BY region, customer ne rassemble les lignes que lorsque les deux valeurs correspondent. Sur la table des commandes, exécute :
SELECT region, customer, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region, customer ORDER BY region, customer;
Les résultats sont East/Ana : deux commandes, 165 ; East/Dara : une, 95 ; North/Chen : deux, 350 ; West/Ben : deux, 140 ; et NULL/Eli : une, 30. La somme des deux résultats de East est égale au total régional de 260.
Un regroupement selon customer, region forme les mêmes combinaisons. L’ordre des colonnes dans GROUP BY ne trie pas le résultat. La clause ORDER BY distincte ci-dessus détermine son affichage, sous réserve de la position de NULL par défaut dans chaque base de données.
Seules les combinaisons présentes dans l’entrée apparaissent. Il n’y a pas de ligne West/Ana avec un effectif de zéro. Le regroupement synthétise les lignes existantes ; il ne crée pas toutes les paires possibles de libellés de catégories.
Ajouter des détails seulement si nécessaire
L’ajout d’une colonne ne divise un groupe que si ses lignes contiennent des valeurs différentes dans cette colonne. Ici, le regroupement par client seul donne déjà cinq groupes. L’ajout de la région en donne toujours cinq, car chaque client n’a qu’une seule valeur de région. Ajouter order_date à un rapport régional crée des groupes plus petits pour les différentes dates et change la question à laquelle le rapport répond.
Regrouper les dates par année et par mois
Dans SQLite, utilise strftime('%Y-%m', order_date) pour créer un libellé comme '2026-02' :
SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY strftime('%Y-%m', order_date) ORDER BY month;
Janvier compte deux commandes pour un total de 200, février en compte trois pour un total de 305 et mars en compte trois pour un total de 275. Dans PostgreSQL, remplace les deux occurrences de strftime('%Y-%m', order_date) par to_char(order_date, 'YYYY-MM') pour une colonne DATE.
Un regroupement selon le seul numéro du mois combine les mêmes mois de différentes années. Janvier 2025 et janvier 2026 formeraient un seul groupe. Conserver l’année dans l’expression de regroupement permet de distinguer les mois du calendrier.
Répéter l’expression dans GROUP BY rend le regroupement explicite. SQLite, PostgreSQL et MySQL acceptent aussi l’alias de sortie, comme dans GROUP BY month ; SQL Server n’accepte pas à cet endroit un alias SELECT du même niveau.
Créer des catégories avec CASE
Une expression CASE peut attribuer un libellé à chaque commande avant le regroupement :
SELECT CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END AS size, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END;
La catégorie large contient 120, 200 et 150 : trois commandes pour un total de 470. La catégorie small contient cinq commandes pour un total de 310. Le seuil est inclus : un montant d’exactement 100 appartient donc à 'large'. La même expression CASE figure dans l’affichage et dans le regroupement afin que les deux utilisent la même définition des catégories.
Points clés
- Plusieurs colonnes de regroupement identifient les combinaisons présentes dans les données.
- L’ajout d’une colonne ne divise que les groupes dans lesquels cette colonne varie.
- Inclus l’année en plus du mois pour distinguer les mois du calendrier.
- Utilise la même expression de catégorie pour le libellé sélectionné et pour le regroupement.
GROUP BYne crée pas les combinaisons absentes avec des effectifs nuls.- L’ordre des colonnes de regroupement ne détermine pas l’ordre du résultat.
3Filtrer des résultats groupés avec HAVING
Un filtre peut modifier les lignes utilisées dans un calcul ou déterminer quelles synthèses terminées apparaissent dans un rapport. Ces choix répondent à des questions différentes. Tu utiliseras HAVING pour conserver des groupes selon leur effectif, leur total ou leur moyenne, puis tu le combineras avec WHERE sans modifier le sens recherché. Suivre l’ordre logique d’une requête permet de placer plus facilement chaque condition et de prévoir le résultat avant d’exécuter le code SQL.
3.1 Conserver les groupes qui remplissent une condition
HAVING teste les groupes après le calcul de leurs agrégats. Utilise-le pour une demande comme « régions dont le total des ventes dépasse 200 ». La condition décrit chaque total régional, et non une commande individuelle.
Calculer d’abord, conserver les groupes ensuite
SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders GROUP BY region HAVING SUM(amount) > 200;
Avant HAVING, les totaux régionaux sont East 260, North 350, West 140 et NULL 30. La condition conserve East avec trois commandes et North avec deux. Elle retire les deux autres groupes du résultat ; elle ne retire pas certaines commandes à l’intérieur de East ou de North.
Dans une requête SQL écrite, place HAVING après GROUP BY et avant ORDER BY. Le tri s’applique ensuite aux groupes conservés par la condition.
Filtrer selon des mesures non affichées
SELECT region FROM orders GROUP BY region HAVING COUNT(*) >= 2; renvoie East, North et West. La base de données peut compter les lignes d’un groupe pour décider s’il remplit la condition sans afficher ce nombre. HAVING et SELECT n’ont pas besoin de listes d’agrégats identiques.
Tu peux combiner des conditions sur les groupes. HAVING COUNT(*) >= 2 AND AVG(amount) > 80 conserve East et North. East compte trois commandes et une moyenne d’environ 86,67 ; North en compte deux et une moyenne de 175. West compte assez de commandes, mais sa moyenne n’est que de 70. Les deux tests doivent être satisfaits, car ils sont reliés par AND ; avec OR, un seul test suffirait.
Trouver les valeurs répétées
Le regroupement et le comptage permettent aussi de trouver des doublons :
SELECT customer, COUNT(*) AS orders FROM orders GROUP BY customer HAVING COUNT(*) > 1;
Ana, Ben et Chen ont chacun deux commandes et remplissent la condition. Dara et Eli en ont une et ne la remplissent pas. Pour trouver les adresses électroniques répétées dans une table de clients, le même modèle regroupe selon email et conserve les effectifs supérieurs à un. L’effectif est le nombre d’enregistrements qui partagent cette valeur.
Utiliser l’expression nécessaire à la condition
Répète l’agrégat dans HAVING : HAVING SUM(amount) > 200. PostgreSQL et le SQL standard n’autorisent pas l’alias de sortie total dans cette condition au même niveau, contrairement à SQLite et MySQL. Un alias peut être utilisé sans problème dans un ORDER BY total DESC ultérieur.
Une valeur arrondie affichée et la valeur testée peuvent différer. La moyenne exacte de East est de 260 divisé par trois. Si tu sélectionnes ROUND(AVG(amount), 2) mais écris HAVING AVG(amount) > 86.67, East est retiré : sa moyenne non arrondie est inférieure à 86,67. North reste. La condition utilise exactement l’expression écrite dans HAVING. Seul HAVING ROUND(AVG(amount), 2) ... testerait la valeur arrondie.
Filtrer le groupe global unique
HAVING peut aussi fonctionner sans GROUP BY explicite. SELECT COUNT(*) FROM orders HAVING COUNT(*) > 5; traite les huit commandes comme un seul groupe, satisfait le test et renvoie une ligne contenant huit. Remplacer la condition par COUNT(*) > 10 ne renvoie aucune ligne, et non une ligne contenant zéro.
PostgreSQL prend en charge ce modèle, tout comme SQLite depuis la version 3.39.0. Dans une installation SQLite plus ancienne, une requête utilisant HAVING nécessite un GROUP BY explicite.
Points clés
HAVINGconserve ou retire des groupes dont les agrégats ont été calculés.- Un agrégat de
HAVINGn’a pas besoin de figurer dansSELECT. - Combine les tests sur les groupes avec
AND,ORetNOT. - Répète les expressions d’agrégation dans
HAVINGpour obtenir des requêtes portables. - Une condition teste sa propre expression, qui peut ne pas être arrondie.
3.2 Choisir entre WHERE et HAVING
Une condition doit être placée là où ce qu’elle décrit existe. Les commandes individuelles existent avant le regroupement. Un total régional n’existe qu’après le regroupement et l’addition des commandes.
Suivre l’ordre logique
Une requête SQL s’écrit dans l’ordre SELECT, FROM, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT. Pour raisonner sur le résultat, suis cet ordre logique :
FROMfournit les lignes.WHEREconserve les lignes qui remplissent la condition.GROUP BYforme des groupes et les agrégats calculent leurs mesures.HAVINGconserve les groupes qui remplissent la condition.SELECTproduit les valeurs de sortie ;DISTINCTsupprime les lignes de résultat en double si cela est demandé.ORDER BYtrie le résultat etLIMITconserve le nombre de lignes demandé.
La base de données peut organiser son exécution interne autrement.
Placer chaque condition au bon niveau
| Demande | Clause |
|---|---|
Commandes avec amount >= 60 | WHERE |
| Commandes dans une plage de dates donnée | WHERE |
Régions avec SUM(amount) > 200 | HAVING |
| Clients ayant passé plus d’une commande | HAVING COUNT(*) > 1 |
WHERE SUM(amount) > 200 échoue parce que le total n’existe pas encore à l’étape du filtrage des lignes. Une condition sur les lignes comme region = 'East' peut être évaluée avant le regroupement et appartient à WHERE.
Suivre les deux filtres
SELECT region, COUNT(*) AS orders, SUM(amount) AS total FROM orders WHERE amount >= 60 GROUP BY region HAVING SUM(amount) > 200;
Retire d’abord les commandes de 45 et de 30. East contient maintenant 120 et 95, North contient 200 et 150, et West contient 80 et 60. Calcule ensuite les totaux de 215, 350 et 140. Enfin, conserve les totaux supérieurs à 200. Le résultat est East avec deux commandes et 215, et North avec deux commandes et 350. La région NULL n’a plus de lignes et ne forme donc jamais de groupe.
Ne pas changer la question en déplaçant un filtre
« Pour chaque région, calculer la moyenne des seules commandes de 60 ou plus » utilise WHERE amount >= 60. La moyenne de East devient 107,5 à partir de 120 et 95.
HAVING MIN(amount) >= 60 demande les régions où chaque montant non NULL atteint le seuil. East est retiré parce que son minimum est de 45 ; North et West restent avec leurs commandes initiales. Le déplacement du test a changé le sens : au lieu de sélectionner des commandes individuelles, il accepte ou rejette des régions entières.
Pour ce rapport régional, region <> 'West' donne le même résultat dans WHERE ou dans HAVING : East et North restent, et le groupe NULL ne satisfait pas non plus la comparaison. WHERE énonce directement la restriction sur les lignes et l’applique avant le regroupement. Pour conserver aussi les régions manquantes, la condition doit comprendre explicitement OR region IS NULL.
Les alias SELECT ne sont pas disponibles dans les clauses WHERE et HAVING antérieures dans PostgreSQL. SQLite permet davantage d’utilisations des alias, mais écrire la colonne d’entrée ou l’expression en entier rend l’étape visée plus claire.
Points clés
WHEREmodifie les entrées des agrégats ;HAVINGfiltre les résultats agrégés.- Place les conditions portant sur l’effectif, le total ou la moyenne d’un groupe dans
HAVING. - Pour prévoir un résultat, suis le filtrage des lignes avant le regroupement.
- Un test sur le minimum d’un groupe peut retirer le groupe entier.
4Calculer des résultats exacts et correctement arrondis
Une requête peut choisir les bonnes lignes et perdre malgré tout la partie fractionnaire de sa réponse. Les types de nombres déterminent la division et les résultats des agrégats, tandis que l’arrondi détermine le nombre de décimales affichées. Tu conserveras les décimales pendant les calculs, choisiras une façon adaptée de traiter un dénominateur vide et n’arrondiras que la mesure finale. Une même expression courte peut se comporter différemment selon la base de données : chaque différence pertinente est donc indiquée.
4.1 Éviter la division entière dans les moyennes et les pourcentages
La division de deux nombres entiers peut supprimer la partie fractionnaire avant même l’affichage de la réponse. Cela compte lorsque tu construis une moyenne ou un pourcentage à partir de totaux et d’effectifs.
Utiliser un opérande décimal avant la division
Dans SQLite et PostgreSQL, 7 / 2 renvoie 3. Avec des entrées entières, SUM(quantity) / COUNT(*) sur la table des commandes renvoie 2 : la division de 19 articles par huit commandes perd sa partie fractionnaire. Dans PostgreSQL, SUM d’une colonne INTEGER renvoie BIGINT, ce qui donne encore une division entière dans ce cas.
Écris 1.0 * SUM(quantity) / COUNT(*) pour obtenir 2,375 dans les deux moteurs. La multiplication par 1,0 crée un opérande décimal avant la division. SUM(quantity) / COUNT(*) * 1.0 donne 2.0 parce que la division a déjà supprimé la partie fractionnaire. Les opérations de même priorité sont évaluées de gauche à droite.
Pour cette table, AVG(quantity) donne directement 2,375 dans SQLite et PostgreSQL. La formule écrite à la main est utile lorsque tu as besoin d’un dénominateur différent ou d’un pourcentage.
Calculer un pourcentage
Trois des huit commandes ont un montant d’au moins 100. Le nombre de ces commandes divisé par le nombre de toutes les commandes mesure leur part. Multiplie par 100,0 :
SELECT 100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*) AS pct_large FROM orders;
Le résultat est de 37,5. Utiliser l’entier 100 à la place produit 37 dans SQLite et pour une division de comptages entiers dans PostgreSQL. Un arrondi ultérieur ne changerait que l’affichage de 37.
Une requête sur toute la table peut ne trouver aucune ligne correspondante. NULLIF(COUNT(*), 0) renvoie NULL lorsque le comptage vaut zéro : 100.0 * COUNT(discount) / NULLIF(COUNT(*), 0) renvoie donc NULL pour une entrée vide. Un dénominateur nul sans protection provoque une erreur dans PostgreSQL ; SQLite renvoie NULL. Une part NULL peut clairement représenter « aucune commande à mesurer ».
Vérifier la base de données et le type d’entrée
| Base de données | Comportement à surveiller |
|---|---|
| SQLite | La division entière tronque le résultat ; AVG renvoie un nombre à virgule flottante. |
| PostgreSQL | La division entière tronque le résultat ; AVG d’une entrée entière ou NUMERIC renvoie NUMERIC. |
| SQL Server | La division entière tronque le résultat ; AVG d’une entrée entière renvoie un entier. |
| MySQL et Oracle | / conserve la partie fractionnaire pour des opérandes entiers. |
Dans SQL Server, utilise AVG(quantity * 1.0) ou convertis les entrées en DECIMAL avant de calculer la moyenne. Dans PostgreSQL, SUM d’une colonne BIGINT renvoie NUMERIC : sa division ne se comporte donc pas nécessairement comme celle de SUM d’une colonne INTEGER. MySQL renvoie DECIMAL pour les sommes d’entrées entières.
Une conversion explicite peut aussi créer l’opérande décimal nécessaire : utilise CAST(SUM(quantity) AS REAL) dans SQLite ou CAST(SUM(quantity) AS NUMERIC) dans PostgreSQL. La conversion en NUMERIC de SQLite peut conserver un entier : cette conversion seule ne garantit donc pas une division décimale.
Distinguer les décimaux exacts des approximations
Les types à virgule flottante stockent des approximations binaires. Dans PostgreSQL, NUMERIC et DECIMAL prennent en charge les valeurs décimales exactes ; les additions en virgule flottante peuvent afficher de petits écarts comme 0.30000000000000004. L’affinité NUMERIC de SQLite ne permet pas un stockage décimal exact. Pour obtenir des totaux monétaires exacts dans SQLite, stocke les centimes sous forme d’entiers, additionne-les et divise par 100,0 pour l’affichage.
Points clés
- Crée un opérande décimal avant de diviser des totaux ou des effectifs entiers.
- Une multiplication après une division entière ne peut pas restituer les chiffres perdus.
- Utilise
NULLIFpour gérer un dénominateur nul. - Les types de résultat des agrégats dépendent à la fois du moteur et du type d’entrée.
- L’affinité
NUMERICde SQLite ne permet pas un stockage décimal exact. - SQL Server nécessite des entrées décimales pour obtenir une moyenne fractionnaire d’entiers.
4.2 Arrondir des résultats agrégés
L’arrondi détermine le nombre de chiffres affichés dans un résultat. Garde toutes les décimales pendant les calculs jusqu’à l’étape finale, afin que les choix d’affichage ne modifient pas la mesure calculée.
Arrondir le résultat d’un agrégat
ROUND(x, n) arrondit à n chiffres après la virgule. ROUND(x) arrondit à l’entier. Par exemple, ROUND(3.14159, 2) vaut 3,14.
SELECT region, ROUND(AVG(amount), 2) AS avg_amount FROM orders GROUP BY region; donne 86,67 pour East, 175 pour North, 70 pour West et 30 pour la région NULL. SQLite peut afficher 175.0 tandis que le résultat NUMERIC de PostgreSQL affiche 175.00. Ces résultats représentent le même nombre. Arrondir un nombre et mettre en forme un libellé textuel de largeur fixe sont deux opérations différentes.
Arrondir après l’addition ou le calcul de la moyenne
Pour trois frais de 0,44, additionne d’abord pour obtenir 1,32, puis arrondis à une décimale pour obtenir 1,3. ROUND(SUM(fee), 1) suit cette séquence. SUM(ROUND(fee, 1)) arrondit chaque frais à 0,4 puis les additionne, ce qui donne 1,2. Un arrondi précoce a modifié le total.
De même, ROUND(100 * 1 / 3, 1) donne 33.0 dans SQLite et PostgreSQL parce que la division entière a déjà produit 33. ROUND(100.0 * 1 / 3, 1) conserve la partie fractionnaire et donne 33.3. Choisis le type de calcul avant d’arrondir.
La somme des parts arrondies peut ne pas être égale à 100 %. Trois parts égales peuvent chacune s’afficher sous la forme 33,3 %, soit un total de 99,9 %. Les parts sous-jacentes couvrent toujours l’ensemble. Recalculer une part arbitraire pour imposer le total affiché modifie le sens du nombre affiché.
Utiliser un type d’entrée pris en charge
PostgreSQL prend en charge ROUND(value, n) à deux arguments pour NUMERIC. Si temp est de type DOUBLE PRECISION, écris ROUND(CAST(AVG(temp) AS NUMERIC), 2). La moyenne de 20,5, 21,25 et 19,0 est de 20,25, et la conversion permet d’utiliser l’arrondi à deux arguments. Avec une colonne entière amount, la moyenne dans PostgreSQL est déjà de type NUMERIC : aucune conversion n’est nécessaire.
Pour les valeurs exactes NUMERIC de PostgreSQL, les valeurs à mi-chemin sont arrondies en s’éloignant de zéro : 2,5 devient 3 et -2,5 devient -3. SQLite donne aussi 3.0 et -3.0 pour ces exemples. L’arrondi en virgule flottante de PostgreSQL dépend de la plateforme ; l’arrondi au nombre pair le plus proche est courant. L’approximation binaire peut aussi placer un décimal juste en dessous de la valeur à mi-chemin visée. Ne fais pas d’un cas particulier d’arrondi en virgule flottante une règle générale pour le calcul décimal exact.
Remarquer deux autres différences entre dialectes
PostgreSQL, MySQL, SQL Server et Oracle utilisent un nombre négatif de décimales pour arrondir à gauche de la virgule. ROUND(1234.5, -2) donne 1 200. SQLite traite un second argument négatif comme zéro et donne 1235.0. Pour arrondir aux centaines dans SQLite, utilise ROUND(x / 100.0) * 100.
La conversion en entier dépend aussi de la base de données : SQLite supprime la partie fractionnaire, donc 2,9 devient 2 ; PostgreSQL l’arrondit à 3. Utilise ROUND lorsque le but est d’arrondir. TRUNC(x, n) dans PostgreSQL supprime des chiffres : TRUNC(2.97, 1) vaut 2.9, tandis que son arrondi à une décimale donne 3.0.
Points clés
- Arrondis le résultat d’un agrégat après avoir terminé son calcul.
- L’arrondi ne peut pas corriger une division entière effectuée auparavant.
- La somme de pourcentages arrondis peut être de 99,9 % ou de 100,1 %.
- Convertis une moyenne à virgule flottante de PostgreSQL en
NUMERICpour utiliserROUNDà deux arguments. - L’arrondi avec un nombre négatif de décimales et la conversion en entier diffèrent selon la base de données.
5Répondre à des questions métier avec des requêtes de synthèse
Les rapports métier nécessitent souvent plusieurs mesures sur une même population : toutes les commandes, les commandes importantes et la part de ces dernières. L’agrégation conditionnelle conserve ces mesures côte à côte. Tu construiras ensuite un rapport complet à partir de sa question, vérifieras les totaux et les catégories manquantes, et utiliseras une seconde étape d’agrégation lorsque la question porte sur les clients ou d’autres groupes plutôt que sur des commandes individuelles.
5.1 Compter et additionner selon une condition avec CASE
L’agrégation conditionnelle permet à différentes mesures d’utiliser différentes contributions tout en conservant le même ensemble global de lignes. Une expression CASE détermine la contribution de chaque ligne à un comptage ou à une somme.
Compter les lignes qui remplissent la condition
COUNT(CASE WHEN amount >= 100 THEN 1 END) compte les commandes d’au moins 100. L’expression renvoie 1 pour une correspondance et NULL pour les autres lignes, car elle n’a pas de ELSE. COUNT ignore ces NULL, ce qui laisse trois correspondances dans la table des commandes.
SUM(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) compte les correspondances en additionnant des uns et des zéros. En présence de lignes en entrée, le résultat est le même. Ce n’est pas le cas de COUNT(CASE WHEN amount >= 100 THEN 1 ELSE 0 END) : 1 et 0 sont tous deux non NULL, donc cette expression compte les huit commandes.
Additionner les montants correspondants
Pour obtenir une somme conditionnelle, renvoie le montant lui-même :
SELECT region, COUNT(*) AS orders, COUNT(CASE WHEN amount >= 100 THEN 1 END) AS large_orders, SUM(CASE WHEN amount >= 100 THEN amount ELSE 0 END) AS large_total FROM orders GROUP BY region;
East compte trois commandes, dont une importante, pour un total de commandes importantes de 120. North compte deux commandes, toutes deux importantes, pour un total de 350. West compte deux commandes, aucune commande importante et un total de commandes importantes de zéro. Le groupe de région NULL compte une commande et affiche zéro pour les deux mesures relatives aux commandes importantes.
Le résultat conserve West parce que ses lignes d’entrée existent toujours. Ajouter WHERE amount >= 100 retirerait les lignes de West avant le regroupement, ce qui ferait disparaître West. Ce filtre ferait aussi compter uniquement les commandes importantes par COUNT(*), supprimant la comparaison avec l’ensemble des commandes.
Utiliser le bon dénominateur
Dans chaque région, calcule le pourcentage de commandes importantes avec ROUND(100.0 * COUNT(CASE WHEN amount >= 100 THEN 1 END) / COUNT(*), 1) AS pct_large. East donne 33,3, North 100,0, West 0,0 et le groupe NULL 0,0. Chaque dénominateur est le nombre de commandes du groupe concerné, et non celui des huit commandes de la table entière.
Pour un rapport sans regroupement qui peut ne contenir aucune ligne, protège le dénominateur avec NULLIF(COUNT(*), 0). Un comptage sur une entrée vide vaut zéro, mais un pourcentage sur une population vide n’a pas de dénominateur.
Créer plusieurs colonnes de catégories
Un seul résultat peut afficher un comptage par région :
SELECT COUNT(CASE WHEN region = 'East' THEN 1 END) AS east, COUNT(CASE WHEN region = 'West' THEN 1 END) AS west, COUNT(CASE WHEN region = 'North' THEN 1 END) AS north FROM orders;
Les effectifs sont trois, deux et deux. La commande d’Eli ne satisfait aucun de ces tests sur les régions nommées. Ajoute COUNT(CASE WHEN region IS NULL THEN 1 END) pour compter la commande dont la région est manquante. Comparer une région NULL à un nom ne produit pas une condition vraie.
Reconnaître d’autres syntaxes
PostgreSQL et SQLite depuis la version 3.30.0 prennent en charge COUNT(*) FILTER (WHERE amount >= 100). Le filtre s’applique à cet agrégat : un COUNT(*) voisin sans filtre compte donc toujours toutes les commandes. MySQL et SQL Server ne prennent pas en charge cette syntaxe d’agrégat avec FILTER ; la forme avec CASE fonctionne dans les deux.
SQLite et MySQL autorisent aussi SUM(amount >= 100) parce que les comparaisons produisent des valeurs de vérité numériques. PostgreSQL rejette SUM appliqué à des booléens. Utilise la forme avec CASE lorsqu’une requête doit fonctionner sur ces différents moteurs.
Points clés
- Place des conditions dans les agrégats pour conserver ensemble des mesures portant sur différents sous-ensembles.
COUNT(CASE ... THEN 1 END)ignore les lignes qui ne remplissent pas la condition.ELSE 0fonctionne pour une somme conditionnelle, mais conduit un comptage conditionnel à compter aussi les lignes qui ne remplissent pas la condition.- Un pourcentage au sein d’un groupe utilise la population de ce groupe comme dénominateur.
- Une clause
FILTERd’agrégat ne modifie que les entrées de cet agrégat. - Utilise
IS NULLpour compter séparément les catégories manquantes.
5.2 Construire et vérifier une requête de synthèse à partir d’une question
Une requête de synthèse part d’une question sur une population à un niveau de détail donné. Traduis ces choix avant d’écrire le code SQL, puis vérifie que le résultat répond toujours à la question initiale.
Construire le rapport dans l’ordre
Pose la question : « Pour chaque mois de 2026 comptant au moins trois commandes, combien de commandes ont été passées et quel était leur montant moyen, à deux décimales près ? »
- Les mesures sont
COUNT(*)etAVG(amount). - La granularité, c’est-à-dire le sens d’une ligne de résultat, est un mois du calendrier.
- La condition sur les lignes conserve les dates de 2026.
- La condition sur les groupes exige au moins trois commandes.
- Le résultat doit être trié par mois, avec la moyenne arrondie pour l’affichage.
Dans SQLite :
SELECT strftime('%Y-%m', order_date) AS month, COUNT(*) AS orders, ROUND(AVG(amount), 2) AS avg_amount FROM orders WHERE order_date >= '2026-01-01' AND order_date < '2027-01-01' GROUP BY strftime('%Y-%m', order_date) HAVING COUNT(*) >= 3 ORDER BY month;
Pour les valeurs de date PostgreSQL, remplace l’expression du mois aux deux endroits par to_char(order_date, 'YYYY-MM'). La plage de dates inclut le début de 2026 et exclut le début de 2027.
Janvier compte deux commandes et ne remplit pas la condition sur les groupes. Février compte trois commandes pour un total de 305, avec une moyenne de 101,67. Mars en compte trois pour un total de 275, avec une moyenne de 91,67. Les groupes conservés représentent six commandes, et non huit, car HAVING a retiré janvier.
Vérifier avant de filtrer les groupes
Exécute d’abord le rapport sans HAVING. La somme des effectifs de tous les groupes doit être égale au nombre de lignes obtenu avec le même filtre WHERE, et la somme des totaux doit être égale au total sans regroupement. Ici, ces vérifications donnent huit et 780. Ne compare pas les totaux des groupes conservés avec l’ensemble de l’entrée après l’exclusion de certains groupes.
Cherche un groupe NULL, examine l’ordre des résultats et recalcule un groupe en filtrant la table initiale. Pour East, WHERE region = 'East' doit donner trois commandes pour un total de 260. Un écart peut révéler une colonne de regroupement supplémentaire, un filtre sur les lignes mal placé ou une expression devenue NULL.
Distinguer la commande moyenne du client moyen
AVG(amount) vaut 97,5 par commande. La dépense moyenne par client porte sur une autre unité : les cinq totaux par client sont 165, 140, 350, 95 et 30. Leur moyenne est de 156.
Calcule-la en deux étapes :
SELECT AVG(total) AS avg_customer_total FROM (SELECT customer, SUM(amount) AS total FROM orders GROUP BY customer) AS per_customer;
La requête interne crée une ligne par client. La requête externe calcule la moyenne de ces lignes, chaque client contribuant une fois. Tous les clients étant nommés, 1.0 * SUM(amount) / COUNT(DISTINCT customer) donne le même résultat de 156. Si les nombres de commandes sont inégaux, la moyenne des montants des commandes correspond à un calcul différent.
Synthétiser les groupes eux-mêmes
Pour compter les clients ayant passé plus d’une commande, liste-les d’abord, puis compte leurs lignes :
SELECT COUNT(*) FROM (SELECT customer FROM orders GROUP BY customer HAVING COUNT(*) > 1) AS repeat_customers;
La réponse est trois. Imbriquer directement des agrégats, comme dans MAX(AVG(amount)) à un même niveau de requête, échoue dans SQLite et PostgreSQL. Pour trouver la région ayant la moyenne la plus élevée, trie les moyennes groupées : ORDER BY AVG(amount) DESC LIMIT 1 renvoie North avec 175. Oracle prend aussi en charge les fonctions de groupe imbriquées, mais un niveau de requête distinct rend les deux calculs explicites. Vérifie les ex aequo lorsqu’un rapport demande un premier résultat.
Points clés
- Détermine les mesures, la granularité, les conditions sur les lignes et les conditions sur les groupes à partir de la question.
- Vérifie les effectifs et les totaux des groupes avant de retirer des groupes avec
HAVING. - Une moyenne par client utilise les totaux par client comme entrées.
- Utilise une requête groupée interne et un agrégat externe pour synthétiser les groupes.
Fonctions d’agrégation SQL : exemples
1Transformer des lignes de commande en chiffres de synthèse fiables
13 étapes
- 1IntroductionLire la question du rapport
Un responsable souhaite obtenir un total des commandes, un nombre de clients et une remise moyenne. Chacun semble être un simple nombre, mais chacun utilise les données d’entrée différemment. Chacun est un agrégat, qui transforme plusieurs lignes en une valeur, et un mauvais choix donne un chiffre trompeur. Nous construirons ces mesures à partir des huit commandes : nous combinerons d’abord les montants, puis choisirons ce qu’il faut compter et déterminerons enfin comment NULL modifie la moyenne. Demande-toi toujours ce qu’une ligne en entrée apporte au résultat.
- 2ExplicationCombiner les montants
Un agrégat combine les valeurs de plusieurs lignes en une synthèse.
SUM(amount)additionne les montants,AVG(amount)calcule leur moyenne, etMIN(amount)etMAX(amount)trouvent les valeurs extrêmes. SansGROUP BY, toutes les commandes qui remplissent la condition forment un seul groupe. Tu peux sélectionner plusieurs agrégats ensemble, car chacun décrit ce même groupe de lignes en entrée. - 3ExempleCalculer une synthèse complète
Les montants des commandes sont 120, 80, 45, 200, 60, 95, 150 et 30. Leur total est de 780. La division de ce total par huit donne une moyenne de 97,5 ; le minimum est de 30 et le maximum de 200.
SELECT SUM(amount) AS total, AVG(amount) AS mean_amount, MIN(amount) AS low, MAX(amount) AS high FROM orders;Le résultat est une ligne contenant quatre mesures nommées.
- 4ExempleChoisir les entrées avant l’addition
Pose maintenant la question pour East uniquement.
WHERE region = 'East'conserve les montants 120, 45 et 95 avant l’exécution de l’agrégat.SELECT SUM(amount) AS total FROM orders WHERE region = 'East';Le résultat est de 260. Les autres régions ne contribuent pas, car leurs commandes ne satisfont pas la condition sur les lignes. Un filtre sur les lignes en entrée modifie le total lui-même, et pas seulement son libellé affiché.
- 5DéfiAssocier une quantité à son prix
Une table de ventes comporte deux lignes : une quantité de 4 au prix unitaire de 6, et une quantité de 2 au prix unitaire de 9. Que renvoie
SUM(quantity * unit_price)et pourquoi la multiplication des deux sommes donne-t-elle un résultat différent ?---reveal---
Les chiffres d’affaires des lignes sont 24 et 18, donc la somme est de 42. La multiplication des sommes donne six fois 15, soit 90, car elle n’associe plus chaque quantité au prix de sa propre ligne.
- 6ExplicationCompter les enregistrements ou les clients
Les commandes indiquent Ana, Ben, Ana, Chen, Ben, Dara, Chen et Eli.
COUNT(customer)compte huit noms enregistrés, y compris les apparitions répétées.COUNT(DISTINCT customer)compte cinq noms différents.La formulation détermine le choix adapté : compter les commandes nécessite de compter les lignes, tandis que compter les clients nécessite de compter les clients distincts. Des noms identiques sur des commandes séparées sont des répétitions attendues, et non des clients supplémentaires.
- 7ExempleCompter la catégorie manquante
La colonne des régions comporte huit lignes mais seulement sept valeurs enregistrées.
COUNT(*)vaut huit,COUNT(region)vaut sept etCOUNT(DISTINCT region)vaut trois.La soustraction du nombre de valeurs enregistrées au nombre de lignes donne une région manquante. Remarque qu’une liste distincte des régions comprendrait aussi une ligne NULL ; le comptage distinct ignore ce NULL au lieu de le traiter comme une quatrième région nommée.
- 8DéfiChoisir le bon comptage
Une colonne de coupons contient NULL, 0, 8, 8 et 0. Quelles valeurs
COUNT(*),COUNT(coupon)etCOUNT(DISTINCT coupon)renvoient-ils, dans cet ordre ?---reveal---
Ils renvoient cinq, quatre et deux. Il y a cinq lignes, quatre valeurs enregistrées et deux valeurs enregistrées différentes, 0 et 8. Les zéros enregistrés comptent ; NULL n’entre dans aucun des deux comptages de colonne.
- 9ExplicationExclure un score inconnu
Considère les scores 80, NULL, 70 et 90. Les scores enregistrés totalisent 240.
AVG(score)divise par les trois scores enregistrés et renvoie 80.Il ne divise pas par les quatre lignes : un score manquant n’est pas un zéro connu. Si la valeur manquante représente un examen manqué qui doit être noté zéro, le calcul recherché devient
AVG(COALESCE(score, 0)), ce qui donne 60. - 10ExemplePlacer la valeur par défaut à la bonne étape
La remise est manquante sur quatre commandes. Dans
SUM(amount - discount), chacune des expressions de ces lignes devient NULL, donc seules les quatre autres contribuent. Leurs montants nets totalisent 345.Si une valeur manquante signifie qu’il n’y a pas de remise, utilise
SUM(amount - COALESCE(discount, 0)). Les huit commandes contribuent alors et le total est de 750. UnCOALESCEplacé autour de la somme déjà calculée ne peut pas rétablir les contributions des lignes omises. - 11DéfiTraiter un groupe sans valeurs connues
Une requête conserve trois lignes dont les montants sont tous NULL. Que renvoient
COUNT(*),COUNT(amount)etSUM(amount)?---reveal---
Ils renvoient trois, zéro et NULL. Les lignes existent, mais aucun montant n’est enregistré pour être compté ou additionné. Une entrée vide donnerait aussi une somme NULL, mais son nombre de lignes serait de zéro. Utilise
COALESCE(SUM(amount), 0)uniquement lorsque le rapport doit afficher ce total manquant sous la forme zéro. - 12DéfiVérifier un calcul et sa population
Quatre enregistrements de prestations comportent des frais de 20, 30, 40 et 50, avec des crédits de 2, NULL, 0 et NULL. Un crédit manquant signifie qu’il n’y a pas de crédit. Quel total net de frais et quel nombre de crédits enregistrés le rapport doit-il afficher ?
---reveal---
Utilise
SUM(charge - COALESCE(credit, 0))pour obtenir un total net de 138, etCOUNT(credit)pour obtenir deux crédits enregistrés. Le crédit nul compte comme enregistré ; remplacer NULL dans la somme conserve les quatre frais. - 13RécapitulatifGarder la mesure liée à ses entrées
Choisis l’agrégat en fonction de la question, puis suis les valeurs qui y entrent. Les comptages distinguent les lignes, les valeurs enregistrées et les valeurs différentes. Pour les moyennes et les calculs sur les lignes, vérifie ce que NULL exclut et si un remplacement a un sens réel. Lorsqu’une réponse paraît surprenante, examine les lignes conservées et leurs contributions avant de modifier le code SQL.
2Construire un rapport au bon niveau de détail
14 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDéterminer ce que représente une ligne de résultat
- 2ExplicationRassembler les lignes par région
- 3ExempleGarder le groupe NULL visible
- 4ConseilTrier avant de conserver les premières lignes
- 5DéfiPrévoir le nombre de groupes restants
- 6ExplicationExpliquer pourquoi un nom est ambigu
- 7ExempleCorriger le rapport selon sa question
- 8ConseilReconnaître un résultat accepté par un système permissif
- 9DéfiChoisir une correction adaptée au sens
- 10ExempleDiviser un groupe selon une seconde valeur
- 11ExplicationCréer un libellé de mois du calendrier
- 12DéfiTrouver l’expression de regroupement
- 13DéfiVérifier la granularité et les libellés du rapport
- 14RécapitulatifLire chaque ligne comme un groupe
3Placer les filtres avant ou après l’agrégation
10 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDistinguer la population de la sélection
- 2ExplicationTester le groupe après calcul
- 3ExempleUtiliser un comptage sans l’afficher
- 4DéfiVérifier la valeur réellement comparée
- 5ExplicationSuivre les étapes logiques du résultat
- 6ExempleRetirer d’abord les petites commandes
- 7ExempleRetirer ensuite les petits totaux de groupes
- 8DéfiRepérer une question modifiée
- 9DéfiCombiner les restrictions sur les lignes et sur les groupes
- 10RécapitulatifDéterminer l’étape à partir de la condition
4Conserver les parties fractionnaires et arrondir le résultat final
11 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionDistinguer le calcul de l’affichage
- 2ExempleTrouver où la partie fractionnaire disparaît
- 3ExplicationIntroduire le nombre décimal assez tôt
- 4ConseilProtéger un dénominateur vide
- 5DéfiCorriger une expression de pourcentage
- 6ExplicationArrondir la moyenne calculée
- 7ExempleVoir comment un arrondi précoce modifie un total
- 8DéfiVérifier une différence entre dialectes
- 9LienChoisir le type pour des montants exacts
- 10DéfiVérifier le type avant l’arrondi
- 11RécapitulatifSuivre le nombre à chaque étape
5Construire et vérifier une synthèse métier
13 étapes
Enregistre cette unité pour suivre chaque Leçon Interactive pas à pas.
- 1IntroductionConserver ensemble toutes les commandes et les commandes sélectionnées
- 2ExplicationFaire contribuer les lignes non correspondantes avec NULL
- 3ExempleGarder l’ensemble du groupe disponible
- 4ExempleAjouter le montant ou ajouter un
- 5DéfiConserver le dénominateur d’une part
- 6ExplicationTraduire la formulation métier
- 7ExempleConstruire le résultat mensuel
- 8ConseilVérifier avant de masquer les groupes
- 9ExplicationChanger l’unité d’entrée d’une moyenne
- 10ExempleLire les deux niveaux de requête
- 11DéfiChoisir la bonne unité pour la moyenne
- 12DéfiCompter uniquement les groupes de clients qui remplissent la condition
- 13RécapitulatifVérifier la population et la granularité
Fonctions d’agrégation SQL : QCM
Série 1 : Lire des comptages, des groupes et des calculs10 Questions Pratiques
Question 1 sur 10
SUM(distance) renvoie-t-il ?Afficher la réponseMasquer la réponse
SUM additionne les trois distances, ce qui donne 71. La plus grande distance, 35, serait le résultat de MAX(distance), tandis qu’une moyenne diviserait la distance cumulée par trois ; aucun des deux ne répond à la demande d’un total.Question 2 sur 10
COUNT(CASE WHEN status = 'closed' THEN 1 ELSE 0 END) ?Afficher la réponseMasquer la réponse
Question 3 sur 10
AVG(delay) renvoie-t-il ?Afficher la réponseMasquer la réponse
AVG divise par leur nombre, trois, ce qui donne huit minutes. Une division par les quatre lignes donnerait six minutes et remplacerait en pratique le délai inconnu par zéro, alors qu’aucune mesure de ce type n’a été enregistrée.Question 4 sur 10
SELECT department, COUNT(*) FROM shifts GROUP BY department renvoie-t-il ?Afficher la réponseMasquer la réponse
Question 5 sur 10
FROM parts GROUP BY category ?Afficher la réponseMasquer la réponse
COUNT(DISTINCT supplier) transforme toutes les valeurs de fournisseur enregistrées dans une catégorie en un seul comptage des fournisseurs différents. Une valeur de fournisseur simple est ambiguë, car la catégorie peut en avoir plusieurs. COUNT(supplier) compterait les enregistrements comportant un fournisseur, y compris les apparitions répétées.Question 6 sur 10
paid_on avec des enregistrements de 2024 à 2026. Quelle expression de regroupement distingue chaque mois du calendrier ?Afficher la réponseMasquer la réponse
Question 7 sur 10
HAVING SUM(amount) > 200 ?Afficher la réponseMasquer la réponse
>= 200. HAVING applique cette comparaison à chaque total d’équipe calculé : il conserve ou retire donc le résultat entier de chaque équipe.Question 8 sur 10
ORDER BY supplier. Les catégories ont plusieurs fournisseurs. Comment afficher d’abord les catégories au coût le plus élevé sans changer la granularité ?Afficher la réponseMasquer la réponse
Question 9 sur 10
SUM(quantity) / COUNT(*) * 1.0 ?Afficher la réponseMasquer la réponse
1.0 * SUM(quantity) / COUNT(*).Question 10 sur 10
ROUND(SUM(fee), 1) mais ne conserve le groupe global qu’avec HAVING SUM(fee) >= 0.8. Quel résultat renvoie-t-elle ?Afficher la réponseMasquer la réponse
Série 2 : Choisir la population et le niveau de détail du rapport10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
COUNT(priority) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
MIN(delivery_date) et MAX(delivery_date), dans cet ordre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
SELECT COUNT(*) FROM (SELECT DISTINCT city, agent FROM visits) AS pairs ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
SUM(cost - credit) et le coût net total recherché, dans cet ordre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
ORDER BY total DESC, customer ASC LIMIT 2 conserve-t-il, en supposant que les noms sont triés par ordre alphabétique ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
ROUND(SUM(fee), 1) et SUM(ROUND(fee, 1)), dans cet ordre, si l’on ignore les infimes écarts d’affichage dus à la virgule flottante ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
SELECT training FROM roster GROUP BY training HAVING COUNT(*) >= 3 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
WHERE amount >= 60 GROUP BY team HAVING AVG(amount) > 80 ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 3 : Combiner valeurs manquantes, types et groupes10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
SELECT 17 / 5 dans SQLite ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
SELECT SUM(quantity * price) FROM stock WHERE department = 'A' ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
COUNT(DISTINCT region) ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
jobs ne correspond à state = 'queued'. Que renvoie SELECT team, COALESCE(SUM(hours), 0) FROM jobs WHERE state = 'queued' GROUP BY team ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
WHERE area IS NOT NULL GROUP BY area, quels sont les effectifs des groupes ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
CASE WHEN amount >= 100 THEN 'large' ELSE 'small' END. Combien de groupes obtient-on ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Série 4 : Analyser et terminer des rapports complets10 Questions Pratiques
Enregistre cette unité pour voir chaque réponse et t'entraîner sur chaque série.
Question 1 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 2 sur 10
WHERE amount >= 30 avec un regroupement de toutes les lignes utilisant HAVING MIN(amount) >= 30. Quelles moyennes apparaissent ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 3 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 4 sur 10
temperature est de type DOUBLE PRECISION. Comment arrondir sa moyenne à deux décimales ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 5 sur 10
COUNT(*) FILTER (WHERE paid = 1) figure à côté de COUNT(*) dans une requête groupée sans clause WHERE. Que restreint le filtre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 6 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 7 sur 10
COUNT(*), COUNT(value) et MAX(value), dans cet ordre ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 8 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 9 sur 10
WHERE zone <> 'West'. Quels groupes de zones peuvent rester ?Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Question 10 sur 10
Afficher la réponseMasquer la réponse
Enregistre cette unité pour voir cette réponse.
Tu bloques sur ton propre exercice ? Aide aux Devoirs
Mots-Clés
A
Agrégation conditionnelle
Alias SELECT
ORDER BY et dont les autres usages dépendent du dialecte.ORDER BY total, mais exige que l’expression d’agrégation soit écrite en entier dans un HAVING du même niveau.Arrondi final
AVG
AVG(amount) donne 97,5 pour huit commandes dont les montants totalisent 780 ; il mesure le montant moyen d’une commande.C
CAST
REAL permet une division décimale, tandis qu’une conversion en NUMERIC peut laisser une valeur entière sous forme d’entier.Catégorie CASE
CASE, qui peut servir de base à un rapport groupé.amount >= 100 place une commande d’exactement 100 dans la catégorie nommée « large ».Clause FILTER d’agrégat
Clé année-mois
COALESCE
COALESCE(SUM(amount), 0) affiche zéro lorsqu’une entrée vide produirait autrement un total NULL.Collation
MIN restent identiques.Colonne de regroupement
Colonne nue
Combinaison distincte
Comparaison sans arrondi
HAVING AVG(amount) >= 86.67 si sa valeur exacte est inférieure.Comptage conditionnel
COUNT.COUNT(CASE WHEN amount >= 100 THEN 1 END) compte les commandes importantes en ignorant les résultats NULL des lignes non correspondantes.Condition sur les groupes
Condition sur les lignes
amount >= 60 peut conserver une commande de East tout en en retirant une autre, avant qu’une synthèse régionale existe.COUNT(*)
COUNT(*) égal à huit, même si aucune région n’est enregistrée pour une commande.COUNT(column)
COUNT(discount) inclut une commande dont la remise vaut zéro, mais exclut une commande dont la remise vaut NULL.COUNT(DISTINCT column)
COUNT(DISTINCT customer) pour obtenir le nombre de clients nommés, même si certains passent plusieurs commandes.Critère de départage
ORDER BY total DESC, customer donne un ordre stable aux totaux par client ex aequo avant l’application d’une limite.D
Dépendance fonctionnelle
Détection des doublons
HAVING COUNT(*) > 1 identifie les clients ayant plusieurs enregistrements de commandes.DISTINCT
SUM(DISTINCT quantity) additionne chaque valeur de quantité une fois : des ventes réelles répétées peuvent donc être exclues du total.Division entière
E
Entrée entièrement NULL
COUNT(x) vaut donc zéro.COUNT(*) égal à quatre et COUNT(discount) égal à zéro lorsqu’un filtre ne sélectionne que ces commandes.Entrée vide
WHERE ne trouve aucun enregistrement correspondant.Expression d’agrégation
SUM(amount - discount) évalue la soustraction pour chaque ligne avant d’additionner les résultats non NULL.Expression de regroupement
CASE.É
Écart d’arrondi
F
Fonction d’agrégation
SUM(amount) pour transformer de nombreux montants de commande en un seul total pour la période sélectionnée.G
Granularité
GROUP BY
GROUP BY region permet à une même requête de calculer un nombre de commandes et un total des montants distincts pour chaque région.Groupe NULL
H
HAVING
HAVING SUM(amount) > 200 conserve les régions selon leur total, sans retirer les petites commandes des groupes conservés.I
IS NULL
WHERE region IS NULL sélectionne les commandes dont la région n’a pas été enregistrée, comme une commande d’un client nommé Eli.M
Mesure
MIN et MAX
MIN(order_date) trouve la date la plus ancienne lorsque la colonne contient des dates ou des dates au format texte ISO uniforme.Moyenne par client
N
Nombre à virgule flottante
DOUBLE PRECISION dans PostgreSQL peut afficher 0.30000000000000004 là où le calcul décimal exact donne 0.3.NULL
amount - discount égal à NULL, ce qui conduit SUM à ignorer la valeur calculée de cette ligne.NULLIF
NULLIF(COUNT(*), 0) rend NULL le dénominateur d’un rapport vide, ce qui évite une erreur de division par zéro dans PostgreSQL.NUMERIC et DECIMAL
O
ONLY_FULL_GROUP_BY
Opérande décimal
ORDER BY
ORDER BY total DESC liste d’abord les totaux de groupes les plus élevés après le calcul de chaque groupe.Ordre logique d’une requête
WHERE avant GROUP BY explique pourquoi le retrait des petites commandes modifie ensuite la moyenne d’une région.P
Pourcentage au sein du groupe
R
Rapprochement
HAVING afin que les groupes exclus n’expliquent pas une différence entre le rapport et le total en entrée.Règle de regroupement
Regroupement sur plusieurs colonnes
ROUND
ROUND(AVG(amount), 2) arrondit la moyenne calculée à deux décimales, sans modifier le calcul effectué auparavant.S
Somme conditionnelle
CASE qui renvoie zéro pour les autres lignes.CASE ; renvoyer 1 compterait les commandes.SUM
SUM(quantity * unit_price) totalise les chiffres d’affaires des lignes après multiplication de chaque quantité par le prix correspondant.T
Table dérivée
FROM, ce qui permet à une seconde requête de synthétiser les lignes créées par la première.Troncature
TRUNC et SQLite tronque lors d’une conversion en entier.TRUNC(2.97, 1) donne 2.9 dans PostgreSQL, tandis que ROUND(2.97, 1) donne 3.0 pour ce décimal exact.V
Valeur à mi-chemin
NUMERIC transforme 2,5 en 3 et -2,5 en -3, en éloignant les deux valeurs à mi-chemin de zéro.W
WHERE
WHERE avant de calculer les totaux mensuels.- 1Modèle relationnel
- 2Requêtes SELECT en SQL
- 3Colonnes calculées SQL
- 4Fonctions d’agrégation SQL
- 5Jointures SQL
- 6Créer des tables SQL
À propos de cette unité
Crée ton propre Matériel d'Étude
Transforme tes notes, diapos et documents en Guides d'Étude, Questions Pratiques, Flashcards et 6 autres outils.