Polarys

Regrouper et agréger

Sous-requêtes et vues

Quand une requête ne suffit pas

Certaines questions demandent un résultat intermédiaire. « Quels clients ont commandé plus que la moyenne » suppose de connaître la moyenne avant de comparer.

Deux outils répondent à ce besoin, et il vaut mieux savoir lequel choisir.

La sous-requête simple

SELECT nom, total
FROM client
WHERE total > (SELECT AVG(total) FROM client);

La sous-requête entre parenthèses renvoie une valeur unique, calculée une fois. C'est lisible et efficace.

Dans une clause IN, elle renvoie une liste :

SELECT nom FROM client
WHERE id IN (SELECT client_id FROM commande WHERE montant > 500);

Attention à un piège réel : si la sous-requête d'un NOT IN peut renvoyer une valeur nulle, le résultat global devient vide, sans erreur ni avertissement. Préférez NOT EXISTS dès qu'un nul est possible.

La sous-requête corrélée, à utiliser avec prudence

Elle référence la ligne de la requête externe, donc elle est réévaluée pour chaque ligne :

SELECT c.nom
FROM client c
WHERE EXISTS (SELECT 1 FROM commande o WHERE o.client_id = c.id);

Sur quelques milliers de lignes, aucun problème. Sur des millions, c'est le motif qui transforme une requête en attente interminable. Une jointure fait souvent le même travail bien plus vite.

L'expression de table commune

Pour enchaîner plusieurs étapes, elle est plus lisible qu'un empilement de parenthèses :

WITH gros_clients AS (
  SELECT client_id, SUM(montant) AS total
  FROM commande
  GROUP BY client_id
  HAVING SUM(montant) > 1000
)
SELECT c.nom, g.total
FROM gros_clients g
JOIN client c ON c.id = g.client_id
ORDER BY g.total DESC;

L'avantage n'est pas la performance mais la lecture : chaque étape porte un nom, et la requête se relit six mois plus tard.

La vue

Une vue est une requête enregistrée sous un nom, qu'on interroge comme une table.

CREATE VIEW commandes_du_mois AS
SELECT * FROM commande WHERE date_commande >= date_trunc('month', now());

Elle sert deux usages honnêtes : éviter de réécrire une requête compliquée, et exposer une partie seulement des données à certains utilisateurs, par exemple une table client sans les coordonnées personnelles.

Deux limites à connaître. Une vue ne stocke rien : interroger une vue coûte ce que coûte sa requête. Et empiler des vues sur des vues produit des requêtes dont personne ne prévoit plus le coût, situation classique des bases anciennes.

À retenir

Sous-requête simple pour une valeur intermédiaire, NOT EXISTS plutôt que NOT IN dès qu'un nul est possible, expression de table commune pour enchaîner lisiblement. Une vue nomme une requête, elle n'accélère rien, et les vues empilées coûtent cher.

Quiz de validation

Quiz - 3 questions

1. Pourquoi préférer NOT EXISTS à NOT IN quand des valeurs nulles sont possibles ?

2. Qu'apporte une vue en termes de performance ?

3. Quel motif transforme une requête en attente interminable sur de gros volumes ?

Suis ta progression

Crée un compte gratuit pour suivre ta progression et accéder à toutes les leçons.