logo

Requêtes SQL avec critères et fonctions d’agrégation

Objectifs Pédagogiques
  • Savoir filtrer les données avec des conditions simples ou multiples.
  • Utiliser efficacement les fonctions d’agrégation (`COUNT`, `AVG`, `SUM`, etc.).
  • Maîtriser les regroupements (`GROUP BY`) et les filtres d’agrégats (`HAVING`).
  • Formuler des requêtes imbriquées simples sans utiliser de jointures.

La grammaire d’une requête SQL

SELECT colonnes
FROM table
[WHERE condition]
[GROUP BY colonne]
[HAVING condition]
[ORDER BY colonne];

Chaque clause joue un rôle précis dans l’ordre d’exécution :

Clause SQL Rôle
FROM Indique la table principale utilisée comme source de données.
WHERE Filtre les lignes avant tout calcul, selon des conditions logiques.
GROUP BY Regroupe les lignes ayant une ou plusieurs colonnes identiques.
HAVING Filtre les groupes après un GROUP BY, souvent avec des agrégats.
SELECT Spécifie les colonnes ou les calculs à afficher.
ORDER BY Trie les résultats affichés (par défaut croissant, ou DESC).
À retenir
Même si elle est écrite après, la clause FROM est traitée en premier par le moteur SQL. L’ordre logique d’exécution diffère souvent de l’ordre d’écriture.

Filtres avec WHERE

SELECT TitreFilm, AnneeSortie
FROM FILM
WHERE Pays = 'USA' AND AnneeSortie BETWEEN 2000 AND 2010;

Utilisation de plusieurs conditions avec AND, OR, BETWEEN, LIKE :

SELECT NomActeur, PrenomActeur
FROM ACTEURS
WHERE NomActeur LIKE 'Mac%' OR DateNaissanceActeur BETWEEN '1980-01-01' AND '1990-12-31';

Opérateurs disponibles dans WHERE

Opérateur Description Exemple
= Égal à Pays = 'USA'
<> ou != Différent de AnneeSortie <> 2023
> , < , >= , <= Comparaison numérique ou alphabétique Budget >= 1000000
BETWEEN ... AND Valeur comprise dans un intervalle AnneeSortie BETWEEN 2000 AND 2010
IN (...) Appartenance à une liste Pays IN ('USA', 'France', 'UK')
NOT IN (...) Exclusion d’une liste Pays NOT IN ('Chine', 'Russie')
LIKE Correspondance partielle avec des jokers TitreFilm LIKE 'Star%'
IS NULL Teste si une valeur est nulle DateSortie IS NULL
IS NOT NULL Teste si une valeur est non nulle DateSortie IS NOT NULL

Utilisation de jokers avec LIKE

Joker Signification Exemple
% remplace n'importe quelle suite de caractères 'Mac%' trouve MacDonald, Macbeth
_ remplace un seul caractère 'M_c' trouve Mac, Mec, Mic
Astuce
Combinez plusieurs conditions avec des parenthèses pour clarifier la logique : WHERE (Pays = 'USA' OR Pays = 'UK') AND AnneeSortie > 2010
À retenir
- La clause WHERE filtre les lignes individuelles avant tout calcul.
- Une bonne utilisation des opérateurs permet d’extraire précisément les données voulues.

Fonctions d’agrégation simples

Fonction Rôle
COUNT(*) Nombre total de lignes
SUM(col) Somme des valeurs
AVG(col) Moyenne
MIN(col) Valeur minimale
MAX(col) Valeur maximale

Exemples :

SELECT COUNT(*) AS nb_films
FROM FILM
WHERE AnneeSortie = 2009;

→ Retourne le nombre de films sortis en 2009 .

SELECT MIN(Budget) AS budget_min, MAX(Budget) AS budget_max
FROM FILM;

→ Donne le plus petit et le plus grand budget dans la base.

SELECT AVG(Budget) AS budget_moyen
FROM FILM
WHERE Pays = 'USA';

→ Affiche le budget moyen des films américains.

Utilisation combinée avec GROUP BY

Les fonctions d’agrégation prennent tout leur sens lorsqu’on les applique à des groupes :

SELECT Pays, COUNT(*) AS nb_films
FROM FILM
GROUP BY Pays;
SELECT AnneeSortie, SUM(Budget) AS total_budget
FROM FILM
GROUP BY AnneeSortie;

Arrondir les résultats

On peut utiliser la fonction ROUND() pour arrondir les résultats numériques :

SELECT AnneeSortie, ROUND(AVG(Budget)) AS budget_moyen
FROM FILM
GROUP BY AnneeSortie;
À retenir
- Les fonctions d’agrégation s’utilisent dans la clause SELECT.
- Elles calculent une valeur unique par groupe ou sur l’ensemble des lignes.
- Pour les appliquer à plusieurs groupes, utilisez GROUP BY.
- Pour filtrer les résultats agrégés, utilisez HAVING (pas WHERE).

Filtrer après regroupement : HAVING

SELECT Pays, COUNT(*) AS nb
FROM FILM
GROUP BY Pays
HAVING nb > 5;

Cette requête affiche uniquement les pays ayant produit plus de 5 films .

Comparer un agrégat avec une valeur :

SELECT AnneeSortie, SUM(Budget) AS total_budget
FROM FILM
GROUP BY AnneeSortie
HAVING total_budget > 500000000;

Affiche les années dont le budget cumulé des films dépasse 500 millions .

Utiliser des fonctions d’agrégation dans HAVING

Contrairement à WHERE, la clause HAVING peut contenir des fonctions comme COUNT(), AVG(), SUM(), etc.

SELECT AnneeSortie, COUNT(*) AS nb_films, AVG(Budget) AS budget_moyen
FROM FILM
GROUP BY AnneeSortie
HAVING AVG(Budget) > 10000000 AND nb_films >= 3;

On sélectionne ici uniquement les années avec au moins 3 films et un budget moyen supérieur à 10 millions .

Différence entre WHERE et HAVING

WHERE HAVING
S'applique avant le regroupement S'applique après le regroupement
Filtre les lignes Filtre les groupes
Ne peut pas utiliser d’agrégats Peut utiliser COUNT, AVG, etc.
-- Mauvais : erreur car AVG ne peut pas être utilisé dans WHERE
SELECT Pays
FROM FILM
WHERE AVG(Budget) > 10000000; -- ❌

-- Correct :
SELECT Pays
FROM FILM
GROUP BY Pays
HAVING AVG(Budget) > 10000000; -- ✅
À retenir
- Utilisez WHERE pour filtrer les lignes individuelles
- Utilisez HAVING pour filtrer les groupes formés par GROUP BY
- Les deux peuvent être combinés dans une même requête

Requêtes imbriquées simples

Les sous-requêtes (ou requêtes imbriquées) permettent d’utiliser le résultat d’une autre requête dans une condition. Elles sont très utiles pour faire des comparaisons dynamiques.

Films au-dessus de la moyenne

SELECT TitreFilm, Budget
FROM FILM
WHERE Budget > (
  SELECT AVG(Budget)
  FROM FILM
);

Affiche les films dont le budget est supérieur à la moyenne de tous les budgets .

Acteurs nés après l’acteur le plus âgé

SELECT NomActeur, PrenomActeur
FROM ACTEURS
WHERE DateNaissanceActeur > (
  SELECT MIN(DateNaissanceActeur)
  FROM ACTEURS
);

Extrait les acteurs plus jeunes que le plus ancien enregistré.

Films sortis la même année qu’un autre film donné

SELECT TitreFilm
FROM FILM
WHERE AnneeSortie = (
  SELECT AnneeSortie
  FROM FILM
  WHERE TitreFilm = 'Inception'
);

Liste les films sortis la même année que "Inception" .

Réalisateurs ayant sorti plus de films que la moyenne

SELECT NomRealisateur, PrenomRealisateur, COUNT(*) AS nb_films
FROM FILM
GROUP BY NomRealisateur, PrenomRealisateur
HAVING nb_films > (
  SELECT AVG(nb)
  FROM (
    SELECT COUNT(*) AS nb
    FROM FILM
    GROUP BY NomRealisateur, PrenomRealisateur
  ) AS sous_stats
);

Cette requête complexe compare le nombre de films par réalisateur à la moyenne des films par réalisateur .

Utilisation de IN et NOT IN

-- Films qui ont un budget égal à celui d’au moins un autre film
SELECT TitreFilm
FROM FILM
WHERE Budget IN (
  SELECT Budget FROM FILM WHERE AnneeSortie = 2020
);
-- Films dont le titre n'existe pas en 2010
SELECT TitreFilm
FROM FILM
WHERE TitreFilm NOT IN (
  SELECT TitreFilm FROM FILM WHERE AnneeSortie = 2010
);
À retenir
- Les requêtes imbriquées permettent de faire des comparaisons dynamiques
- Elles peuvent être placées dans les clauses `WHERE`, `HAVING`, ou même `SELECT`
- Utilisez `IN`, `NOT IN`, `=`, `<`, `>` avec des sous-requêtes retournant une ou plusieurs valeurs

Requêtes avancées sans jointure

Nombre de films par année (seulement si ≥ 3)

SELECT AnneeSortie, COUNT(*) AS nb
FROM FILM
GROUP BY AnneeSortie
HAVING nb >= 3
ORDER BY AnneeSortie;

Affiche les années où au moins 3 films sont sortis.

Films avec le budget maximum

SELECT TitreFilm, Budget
FROM FILM
WHERE Budget = (
  SELECT MAX(Budget) FROM FILM
);

Extrait le ou les films ayant le plus gros budget enregistré.

Pays ayant une moyenne de budget supérieure à la médiane approximative

SELECT Pays, AVG(Budget) AS budget_moyen
FROM FILM
GROUP BY Pays
HAVING AVG(Budget) > (
  SELECT AVG(Budget)
  FROM (
    SELECT Budget
    FROM FILM
    ORDER BY Budget
    LIMIT 1000000000 OFFSET (
      SELECT COUNT(*)/2 FROM FILM
    )
  ) AS approx_median
);

Exemple avancé d’approximation de médiane via sous-requête (nécessite adaptation selon le SGBD).

Années avec le budget total le plus élevé (top 3)

SELECT AnneeSortie, SUM(Budget) AS total
FROM FILM
GROUP BY AnneeSortie
ORDER BY total DESC
LIMIT 3;

Retourne les 3 années ayant généré le plus de budget cumulé .

Films dont le budget est strictement supérieur à tous les autres films de leur année

SELECT f1.TitreFilm, f1.AnneeSortie, f1.Budget
FROM FILM f1
WHERE f1.Budget > ALL (
  SELECT f2.Budget
  FROM FILM f2
  WHERE f2.AnneeSortie = f1.AnneeSortie AND f2.TitreFilm <> f1.TitreFilm
);

Chaque film sélectionné est le plus cher de son année, sans utiliser de jointure explicite.

À retenir
- Les requêtes avancées peuvent combiner `GROUP BY`, `HAVING`, `ORDER BY` et sous-requêtes.
- Il est possible de croiser des données entre lignes sans jointure en s’appuyant sur des sous-requêtes corrélées
- Les requêtes avec `ALL`, `ANY`, `LIMIT`, `ORDER BY` et `HAVING` permettent une analyse fine et ciblée.

Tri des résultats : ORDER BY

SELECT TitreFilm, AnneeSortie, Budget
FROM FILM
WHERE Pays = 'USA'
ORDER BY Budget DESC;

Cette requête affiche les films américains triés par budget décroissant (du plus cher au moins cher).

Trier par plusieurs colonnes

SELECT TitreFilm, AnneeSortie, Budget
FROM FILM
ORDER BY AnneeSortie ASC, Budget DESC;

Les films sont d’abord triés par année croissante, puis à budget décroissant à l’intérieur de chaque année.

Trier après agrégation

SELECT AnneeSortie, COUNT(*) AS nb_films
FROM FILM
GROUP BY AnneeSortie
ORDER BY nb_films DESC;

Affiche les années où le plus de films sont sortis, par ordre décroissant de nombre.

Trier les valeurs nulles

Le comportement par défaut des NULL dépend du système de gestion (MySQL, PostgreSQL, etc.). Pour forcer leur position :

ORDER BY DateSortie IS NULL ASC, DateSortie ASC;

Les dates connues sont affichées en premier, les NULL en dernier.

Utiliser un alias dans ORDER BY

SELECT AnneeSortie, AVG(Budget) AS budget_moyen
FROM FILM
GROUP BY AnneeSortie
ORDER BY budget_moyen DESC;

On peut utiliser le nom de colonne ou son alias défini dans SELECT.

Bonnes pratiques
- Utilisez `ORDER BY` pour faciliter la lecture et la hiérarchisation des résultats.
- Combinez `GROUP BY`, `HAVING`, et `ORDER BY` pour construire des requêtes puissantes.
- Pour plus de clarté, utilisez toujours des aliases lisibles dans `SELECT`, surtout quand vous triez.