Filtrer sur un résultat de fenêtre
Pourquoi vous devez encapsuler une fonction de fenêtre dans une sous-requête ou un CTE pour le filtrer
Filtrer sur un résultat de fenêtre est une leçon Coding 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 Coding Interview Prep, et ta progression se synchronise sur le web et l'application CoddyKit. Le cours Coding Interview Prep comprend 4 leçons au total.
Pourquoi vous ne pouvez pas filtrer une fenêtre dans WHERE
Un « piège » fréquent en entretien : écrire WHERE ROW_NUMBER() OVER (...) = 1 génère une erreur. Les fonctions de fenêtre ne sont pas autorisées dans WHERE, GROUP BY ou HAVING.
La raison tient à l'ordre logique d'exécution. WHERE s'exécute pour sélectionner les lignes avant l'évaluation des fonctions de fenêtre. La fenêtre n'a même pas encore été calculée : elle ne peut donc pas être utilisée dans un filtre.
L'explication par l'ordre d'exécution
Les fonctions de fenêtre sont calculées lors d'une phase dédiée, située après FROM, WHERE, GROUP BY et HAVING, mais avant le ORDER BY et le LIMIT finaux.
Ainsi, au moment où WHERE s'exécute, le rang ou le numéro de ligne n'existe pas encore. Pour filtrer dessus, vous devez d'abord laisser la fenêtre se terminer, puis filtrer la colonne produite dans une couche de requête externe.
Le modèle d'encapsulation par sous-requête
La correction standard consiste à calculer la fonction de fenêtre dans une requête interne (une table dérivée), à donner un alias au résultat, puis à filtrer cet alias dans le WHERE externe.
La table dérivée doit avoir un alias (t ici) — les recruteurs remarquent les candidats qui l'oublient. rn est alors une colonne ordinaire que la requête externe peut comparer.
SELECT *
FROM (
SELECT
name, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
FROM employees
) t
WHERE rn = 1;Le modèle CTE (souvent plus lisible)
Une expression de table commune accomplit la même tâche avec une structure plus lisible. Définissez le classement dans une étape WITH, puis filtrez-le dans la requête principale.
Elle est fonctionnellement identique à la sous-requête, mais les recruteurs préfèrent généralement les CTE en programmation en direct, car l'intention se lit de haut en bas.
WITH ranked AS (
SELECT
name, department, salary,
ROW_NUMBER() OVER (PARTITION BY department ORDER BY salary DESC) AS rn
FROM employees
)
SELECT name, department, salary
FROM ranked
WHERE rn = 1;Exemple détaillé : les N premières lignes par groupe
Le problème de fonction de fenêtre le plus fréquent : « les trois employés les mieux payés de chaque service ». Classez les employés dans la CTE, puis conservez rn <= 3 à l'extérieur.
Choisissez la fonction de classement selon le comportement souhaité en cas d'égalité : ROW_NUMBER limite à exactement trois lignes par service ; utilisez RANK/DENSE_RANK si les égalités à la limite doivent être incluses.
WITH ranked AS (
SELECT department, name, salary,
ROW_NUMBER() OVER (
PARTITION BY department ORDER BY salary DESC
) AS rn
FROM employees
)
SELECT department, name, salary
FROM ranked
WHERE rn <= 3
ORDER BY department, rn;Exemple détaillé : filtrer sur un total cumulé
Le modèle d'encapsulation ne sert pas uniquement aux rangs. Tout résultat de fenêtre — totaux cumulés, moyennes mobiles, écarts de LAG — doit être filtré de la même manière.
Ici, nous calculons un solde cumulé, puis ne conservons que les lignes où il a dépassé 1 000 pour la première fois. Le filtre se trouve à l'extérieur de la couche de fenêtre.
WITH balances AS (
SELECT
account_id, txn_date, amount,
SUM(amount) OVER (
PARTITION BY account_id ORDER BY txn_date
) AS running_balance
FROM transactions
)
SELECT *
FROM balances
WHERE running_balance > 1000;QUALIFY : le raccourci de certaines bases de données
Snowflake, BigQuery, Teradata et DuckDB proposent une clause QUALIFY qui filtre directement les résultats de fenêtre, sans encapsulation. Elle s'exécute après les fonctions de fenêtre, exactement à l'endroit souhaité.
Mentionnez QUALIFY pour montrer l'étendue de vos connaissances, mais précisez qu'il ne fait pas partie du standard SQL et qu'il est absent de PostgreSQL, MySQL et SQL Server, où la sous-requête ou la CTE reste nécessaire.
-- Snowflake / BigQuery only:
SELECT department, name, salary
FROM employees
QUALIFY ROW_NUMBER() OVER (
PARTITION BY department ORDER BY salary DESC
) = 1;Ne confondez pas HAVING et le filtrage de fenêtre
Les candidats essaient parfois d'utiliser HAVING pour filtrer un rang. HAVING filtre les groupes après l'agrégation de GROUP BY et s'exécute toujours avant les fonctions de fenêtre : il ne peut donc pas non plus faire référence à une colonne de fenêtre.
WHERE→ filtre les lignes avant le regroupement et avant les fenêtres.HAVING→ filtre les groupes agrégés, toujours avant les fenêtres.- Filtrer une fenêtre → nécessite une requête externe (ou
QUALIFY).
Combiner un préfiltre avec un filtre de fenêtre
Il est fréquent de filtrer à la fois avant et après la fenêtre. Appliquez les filtres ordinaires sur les lignes dans le WHERE interne (afin que la fenêtre ne voie que les lignes pertinentes), puis filtrez le résultat de la fenêtre dans la requête externe.
Dans cet exemple, nous commençons par limiter les résultats aux employés actifs, puis nous sélectionnons parmi eux la personne la mieux rémunérée de chaque service. Placer WHERE active à l'intérieur modifie les lignes qui sont classées.
WITH ranked AS (
SELECT department, name, salary,
ROW_NUMBER() OVER (
PARTITION BY department ORDER BY salary DESC
) AS rn
FROM employees
WHERE is_active = true -- pre-filter before ranking
)
SELECT * FROM ranked
WHERE rn = 1; -- post-filter on the windowRemarque sur les performances
Les recruteurs peuvent demander si l'encapsulation nuit aux performances. Généralement, non : l'optimiseur traite la sous-requête ou la CTE comme une partie d'un seul plan et calcule la fenêtre une seule fois. Il n'y a pas d'analyse supplémentaire simplement parce que vous l'avez encapsulée.
Une réserve : dans certains moteurs, une CTE peut constituer une barrière d'optimisation (et être matérialisée), de sorte qu'une table dérivée ou QUALIFY puisse produire un meilleur plan pour les chemins très sollicités. Analysez le plan avec EXPLAIN si cela est important.
Erreurs fréquentes
Liste de vérification finale :
- Ne placez jamais une fonction de fenêtre dans
WHERE/HAVING: cela génère une erreur. - Donnez toujours un alias à la table dérivée ; une sous-requête sans nom dans
FROMest rejetée. - Choisissez la fonction de classement selon le comportement en cas d'égalité requis par la question.
- Utilisez
QUALIFYuniquement lorsqu'il est pris en charge ; sinon, utilisez l'encapsulation par CTE ou sous-requête.
Vérification rapide
Pourquoi le filtrage d'une fonction de fenêtre nécessite-t-il une encapsulation ?
Récapitulatif : filtrer les résultats de fenêtre
Vous maîtrisez maintenant l'ensemble du fonctionnement des fonctions de fenêtre de classement :
- Les fonctions de fenêtre s'exécutent après
WHERE/GROUP BY/HAVING, vous ne pouvez donc pas les filtrer à ces endroits. - Encapsulez la fenêtre dans une sous-requête ou une CTE (toujours avec un alias), puis filtrez le résultat dans la requête externe.
- Cette technique permet de sélectionner les N premières lignes par groupe, la ligne la plus récente par clé et les seuils de totaux cumulés.
QUALIFYest un raccourci pratique, non standard, disponible uniquement dans Snowflake/BigQuery.
Vous disposez désormais de l'ensemble des outils de classement que les recruteurs évaluent le plus souvent.
Questions Fréquemment Posées
La leçon « Filtrer sur un résultat de fenêtre » est-elle gratuite ?
Oui — le texte complet de « Filtrer sur un résultat de fenêtre » 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 Coding Interview Prep, passe à CoddyKit PRO. Le cours Coding Interview Prep comprend 4 leçons au total.
Qu'est-ce que j'apprendrai dans « Filtrer sur un résultat de fenêtre » ?
Pourquoi vous devez encapsuler une fonction de fenêtre dans une sous-requête ou un CTE pour le filtrer Tu pratiques Coding 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 Coding Interview Prep ?
Aucune expérience préalable n'est requise. Coding 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 un résultat de fenêtre » ?
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 Coding Interview Prep ?
Oui. Chaque leçon Coding 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
- OVER, PARTITION BY et ORDER BY
- ROW_NUMBER pour une numérotation unique
- RANK ou DENSE_RANK en cas d’égalité
- Filtrer sur un résultat de fenêtre