Filtrer sur des valeurs calculées
Pourquoi les fonctions appliquées aux colonnes empêchent l’utilisation des index et comment les recruteurs vous interrogent sur ce point
Filtrer sur des valeurs calculées est une leçon SQL Interview Prep gratuite sur CoddyKit. Ceci est la leçon 4 sur 4. Tu peux lire la leçon complète ci-dessous gratuitement — puis la pratiquer en direct dans le navigateur avec un éditeur de code intégré et un tuteur IA 24/7. Elle fait partie du parcours d'apprentissage SQL Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours SQL Interview Prep comprend 4 leçons au total.
Pourquoi cette question permet de distinguer les niveaux
L'énoncé semble innocent : cette requête est correcte, mais lente : pourquoi ? Souvent, la réponse est que la clause WHERE englobe une colonne indexée dans une fonction. Le prédicat devient alors non sargable : l'optimiseur ne peut plus utiliser l'index et doit parcourir chaque ligne.
Cette leçon explique la sargabilité, montre les réécritures attendues par les recruteurs et précise où un filtre calculé doit réellement être placé.
La sargabilité en une définition
Sargable (argument de recherche ABLE) signifie qu'un prédicat peut utiliser un index pour rechercher directement les lignes correspondantes. Règle générale : la colonne indexée doit apparaître sans transformation d'un côté de la comparaison, et non être enfouie dans une fonction ou une expression.
- Sargable :
col = 5,col > 100,col LIKE 'abc%' - Non sargable :
FUNC(col) = 5,col + 1 > 100
L'anti-modèle de la fonction appliquée à une colonne
Ici, l'objectif est de sélectionner les commandes passées en 2024. Entourer la colonne de YEAR() force le moteur à calculer l'année pour chaque ligne avant de pouvoir comparer, ce qui rend l'index sur order_date inutilisable.
La requête renvoie le bon résultat, mais parcourt toute la table. Sur une grande table, c'est la différence entre des millisecondes et des minutes.
-- non-sargable: function on the indexed column
SELECT *
FROM orders
WHERE YEAR(order_date) = 2024;Réécrire sous forme d'intervalle
La correction consiste à laisser order_date sans transformation et à exprimer la condition sous la forme d'un intervalle semi-ouvert. L'index sur order_date peut alors accéder directement au début de 2024 et s'arrêter en 2025.
Le résultat est identique, mais avec un parcours d'intervalle de l'index au lieu d'un parcours complet. Cette réécriture est la correction de sargabilité la plus fréquemment évaluée en entretien.
-- sargable: column stays bare
SELECT *
FROM orders
WHERE order_date >= '2024-01-01'
AND order_date < '2025-01-01';Arithmétique appliquée à la colonne
Le même problème se cache dans les opérations arithmétiques. WHERE salary + bonus > 100000 ou WHERE price * 0.9 < 50 effectuent toutes deux un calcul sur la colonne et bloquent l'utilisation de l'index.
Déplacez autant que possible le calcul du côté de la constante : réécrivez price * 0.9 < 50 sous la forme price < 50 / 0.9. La valeur littérale est calculée une seule fois et price reste sans transformation et utilisable par l'index.
-- before: math on the column (non-sargable)
WHERE price * 0.9 < 50
-- after: math on the constant (sargable)
WHERE price < 50 / 0.9La variante de recherche insensible à la casse
WHERE LOWER(email) = 'a@b.com' n'est pas sargable avec un index simple sur email, car l'adresse de chaque ligne est d'abord convertie en minuscules.
Deux corrections adaptées à la production : stocker une copie normalisée en minuscules et créer un index dessus, ou créer un index fonctionnel sur LOWER(email) afin que l'expression elle-même soit indexée. Citer l'option de l'index fonctionnel montre une expérience concrète du terrain.
-- functional index makes the expression sargable
CREATE INDEX idx_email_lower ON users (LOWER(email));
SELECT * FROM users WHERE LOWER(email) = 'a@b.com';Quand un calcul est réellement nécessaire
Parfois, le filtre dépend réellement d'une valeur calculée pour laquelle aucune réécriture sous forme d'intervalle n'est possible, par exemple pour filtrer selon un ratio. Vous ne pouvez toujours pas faire référence à un alias de SELECT dans WHERE, car la clause WHERE est évaluée avant la liste SELECT.
Vous devez donc soit répéter l'expression dans WHERE, soit englober la requête dans une sous-requête / une CTE et filtrer la colonne calculée dans la requête externe.
SELECT *
FROM (
SELECT *, revenue / NULLIF(visits, 0) AS rev_per_visit
FROM stats
) t
WHERE t.rev_per_visit > 2.5;Les agrégats vont dans HAVING, pas dans WHERE
Un calcul qui est un agrégat ne peut pas du tout figurer dans WHERE, car WHERE filtre les lignes individuelles avant le regroupement. WHERE SUM(amount) > 1000 est une erreur.
Les filtres sur les agrégats doivent se trouver dans HAVING, qui s'exécute après GROUP BY. Savoir quelle clause voit le calcul constitue en soi une question fréquente sur l'ordre d'exécution.
SELECT customer_id, SUM(amount) AS total
FROM orders
GROUP BY customer_id
HAVING SUM(amount) > 1000;Comment les recruteurs vous questionnent à ce sujet
On vous présente une requête lente contenant une fonction appliquée à une colonne et on vous demande de l'accélérer sans modifier le résultat. Votre démarche :
- Identifier la fonction appliquée à la colonne comme non sargable
- Réécrire la condition pour laisser la colonne sans transformation (intervalle ou calcul du côté de la constante)
- Si aucune réécriture n'est possible, proposer un index fonctionnel ou une colonne calculée stockée
Mentionner EXPLAIN pour confirmer que le plan est passé d'un parcours séquentiel à un parcours d'index apporte la touche finale.
Conscience des compromis
Soyez nuancé : les index et les index fonctionnels accélèrent les lectures, mais ralentissent les écritures et consomment de l'espace de stockage. Sur une petite table, un parcours complet convient et ajouter un index serait un effort inutile.
La réponse d'un développeur expérimenté est conditionnelle : si cette colonne est volumineuse et fait fréquemment l'objet de filtres de cette manière, rendez le prédicat sargable ou ajoutez un index fonctionnel ; sinon, laissez-la telle quelle. En entretien, le contexte prime sur les dogmes.
Les index fonctionnels rendent un calcul indexable
Vous devez parfois réellement filtrer sur une valeur transformée, par exemple pour une correspondance insensible à la casse. Au lieu de renoncer aux index, créez un index d’expression (fonctionnel) sur l’expression exacte utilisée pour le filtrage.
- L’optimiseur peut alors utiliser l’index, même si une fonction enveloppe la colonne.
- L’expression de l’index doit correspondre exactement à l’expression du prédicat.
-- index the expression you filter on
CREATE INDEX idx_users_lower_email ON users (lower(email));
-- now this predicate stays sargable
SELECT * FROM users WHERE lower(email) = 'amy@example.com';Vérification rapide
Identifiez le prédicat que l'optimiseur peut traiter avec un index.
Récapitulatif
Points essentiels :
- Un prédicat est sargable lorsque la colonne indexée apparaît sans transformation, et non dans une fonction ou une opération arithmétique
- Réécrivez
YEAR(col) = 2024sous forme d'intervalle semi-ouvert ; déplacez les calculs du côté de la constante - Pour les expressions incontournables, utilisez un index fonctionnel ou une colonne calculée stockée
- Vous ne pouvez pas utiliser un alias de
SELECTdansWHERE; les agrégats vont dansHAVING
La question classique porte sur une requête lente ; la correction classique consiste à laisser la colonne sans transformation.
Questions Fréquemment Posées
La leçon « Filtrer sur des valeurs calculées » est-elle gratuite ?
Oui — le texte complet de « Filtrer sur des valeurs calculées » est gratuit à lire ici sur le web. Pour la pratiquer de manière interactive (un éditeur de code intégré et un tuteur IA 24/7) et déverrouiller le reste du cours SQL Interview Prep, passe à CoddyKit PRO. Le cours SQL Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Filtrer sur des valeurs calculées » ?
Pourquoi les fonctions appliquées aux colonnes empêchent l’utilisation des index et comment les recruteurs vous interrogent sur ce point Tu pratiques SQL Interview Prep avec du code pratique que tu exécutes directement dans le navigateur, et un tuteur IA 24/7 répond à tes questions au fur et à mesure que tu avances dans la leçon.
Dois-je avoir de l'expérience pour commencer SQL Interview Prep ?
Aucune expérience préalable n'est requise. SQL Interview Prep sur CoddyKit est structuré pour les débutants jusqu'aux apprenants avancés, donc tu peux commencer ici ou depuis le début et avancer à ton rythme. Ceci est la leçon 4 sur 4.
Combien de temps prend la leçon « Filtrer sur des valeurs calculées » ?
La plupart des leçons CoddyKit prennent environ 5–10 minutes. Chacune est courte et interactive, tu progresses régulièrement et tu repiques exactement où tu t'es arrêté sur le web et l'app.
Peux-tu écrire et exécuter du code dans cette leçon SQL Interview Prep ?
Oui. Chaque leçon SQL Interview Prep inclut un éditeur de code intégré, tu écris et exécutes du vrai code directement dans ton navigateur et tu reçois des retours IA instantanés — aucune configuration locale requise.
Toutes les leçons de ce cours
- Priorité de AND et OR et usage des parenthèses
- BETWEEN, IN et limites inclusives
- LIKE, caractères génériques et échappement
- Filtrer sur des valeurs calculées