Les candidats échouent souvent sur six concepts SQL clés en entretien, comme les fonctions fenêtre, HAVING, les auto-joints ou la gestion des NULLs. Maîtriser ces notions avec des exemples précis augmente nettement vos chances de succès en recrutement.
3 principaux points à retenir.
- Comprendre et maîtriser les fonctions fenêtre avec ORDER BY pour un résultat fiable.
- Différencier WHERE et HAVING pour filtrer avant ou après agrégation.
- Gérer correctement les NULL, joins et déduplications avec les bonnes techniques SQL.
Pourquoi faut-il maîtriser les fonctions fenêtre en SQL ?
Au-delà des bases du SQL, maîtriser les fonctions fenêtre est un passage obligé pour quiconque souhaite plonger dans l’analyse de données. Pourquoi ? Parce qu’elles vous permettent d’effectuer des calculs analytiques sur un ensemble de lignes en rapport avec la ligne courante, tout cela sans perdre de détails. Imaginez que vous devez analyser la rétention des utilisateurs sur une plateforme : les fonctions fenêtre sont vos alliées pour calculer la moyenne des transactions des utilisateurs sans agrégation. Incroyable, n’est-ce pas ?
Un point crucial à ne pas négliger est l’utilisation de ORDER BY. Ce dernier est la clé pour garantir des résultats déterministes et pertinents. En l’absence d’un ordre explicite, les résultats peuvent devenir complètement aléatoires, vous rendant ainsi incapable d’en tirer des conclusions fiables. C’est comme créer un classement sans avoir établi de critères clairs ; ça ne fait pas sens.
Un exemple classique d’erreur est l’oubli d’ORDER BY dans des fonctions comme LAG ou LEAD. Regardez ce script :
SELECT user_id, transaction_amount,
LAG(transaction_amount) OVER (PARTITION BY user_id) AS previous_transaction
FROM transactions;
Sans ORDER BY, les résultats peuvent varier d’une exécution à l’autre. Corrigeons cela :
SELECT user_id, transaction_amount,
LAG(transaction_amount) OVER (PARTITION BY user_id ORDER BY transaction_date) AS previous_transaction
FROM transactions;
En ajoutant ORDER BY transaction_date, on garantit que la comparaison se fait correctement dans le temps. En somme, PARTITION BY segmente vos données, et sans un ordre clair, vos analyses peuvent devenir un véritable casse-tête.
Voici un tableau récapitulatif des différences entre l’utilisation des fonctions fenêtre avec ou sans ORDER BY :
| Critère | Avec ORDER BY | Sans ORDER BY |
|---|---|---|
| Résultat | Déterministe et pertinent | Aléatoire et peu fiable |
| Utilisation | Analytique précise | Résultats imprécis |
Pour en savoir plus sur les questions d’entretien SQL, consultez cet article intéressant ici.
Comment différencier WHERE et HAVING en SQL ?
Pour bien comprendre pourquoi il est crucial de savoir différencier WHERE et HAVING en SQL, il faut d’abord plonger dans le pipeline d’exécution des requêtes SQL. Ce pipeline opère selon un ordre spécifique : d’abord, on filtre les lignes avec WHERE, ensuite, on regroupe ces lignes, et enfin, on peut appliquer des agrégats (comme SUM, AVG, etc.). C’est là que HAVING entre en jeu : il filtre les résultats agrégés après que le travail de groupe ait été effectué.
Visualisez cela comme une chaîne de montage dans une usine : WHERE est le premier poste, où des pièces sont triées avant d’atteindre le domaine de l’assemblage (l’agrégation). Après l’assemblage, HAVING s’assure que seuls les produits finaux répondant à certains critères quittent l’usine.
Utiliser un agrégat dans une condition WHERE déclenche une erreur, car SQL essaie d’évaluer le résultat d’un agrégat avant qu’il n’ait eu lieu. Imaginez essayer de juger la qualité d’un vin avant même qu’il ne soit en bouteille. Cela n’a simplement pas de sens.
Un exemple concret aidera à illustrer cela. Supposons que nous voulons calculer le revenu total par winery, mais avec une condition : les wineries doivent avoir une note minimale de 80. Commençons par une syntaxe incorrecte :
SELECT winery, SUM(revenu)
FROM ventes
WHERE note >= 80
GROUP BY winery;
Cette requête ne fonctionnera pas. Nous ne pouvons pas filtrer par note avant d’aggréger les revenus. Voici comment cela devrait se présenter, en utilisant HAVING à la place :
SELECT winery, SUM(revenu)
FROM ventes
GROUP BY winery
HAVING AVG(note) >= 80;
L’utilisation de HAVING ici permet de s’assurer que nous ne conservons que les wineries qui, une fois les notes moyennes calculées, atteignent la note minimale souhaitée.
Comprendre la logique d’agrégation est essentiel pour éviter ces erreurs fréquentes qui peuvent couler vos candidatures lors des entretiens. Des confusions autour de WHERE et HAVING font partie des pièges classiques. Pour approfondir encore plus ce sujet, consultez cette discussion intéressante.
Quand privilégier un auto-joint plutôt qu’une sous-requête ?
Quand on parle des concepts SQL essentiels, la distinction entre un auto-joint (self-join) et une sous-requête peut vraiment faire la différence lors d’un entretien. Mais qu’est-ce qu’un auto-joint exactement ? En gros, c’est une manière de joindre une table à elle-même. Cela permet de comparer des lignes au sein de la même table, ce qui est particulièrement utile pour les analyses temporelles.
Imaginez que vous devez analyser les taux de change d’une devise à deux dates différentes. Plutôt que de jongler avec des sous-requêtes complexes, un auto-joint peut simplifier votre requête et améliorer les performances. Prenons un exemple. Supposons que vous ayez une table appelée taux_de_change avec les colonnes devise, date, et taux. Voici comment vous pourriez construire votre requête :
SELECT a.devise, a.taux AS taux_date1, b.taux AS taux_date2
FROM taux_de_change a
JOIN taux_de_change b ON a.devise = b.devise
WHERE a.date = '2023-01-01' AND b.date = '2023-01-02';
Dans cet exemple, nous avons deux alias pour la même table : a et b. On les utilise pour comparer les taux de change de la même devise à deux dates distinctes. La beauté du self-join réside dans sa simplicité, rendant le code plus lisible et ainsi favorisant sa maintenabilité – des compétences clés que les recruteurs recherchent lors des entretiens.
À l’inverse, une sous-requête corrélée pourrait nécessiter une structure bien plus complexe, donc davantage de ressources pour l’exécuter. Selon les experts en SQL, l’utilisation d’un auto-joint non seulement réduit le temps de traitement, mais améliore également la clarté du code. Pour creuser davantage sur la distinction entre ces deux approches, n’hésitez pas à consulter cet article sur SQL.
En fin de compte, maîtriser l’art de l’auto-joint vous donnera un indéniable avantage en entretien. C’est une compétence qui montre que vous pensez à la performance, à la lisibilité et à la durabilité de votre code. Qui pourrait dire non à ça ?
Pourquoi préférer les CTE aux sous-requêtes imbriquées ?
Les Common Table Expressions, ou CTE, sont souvent perçues comme une bonne pratique pour améliorer la lisibilité des requêtes SQL. Pourquoi ? Imaginez un casse-tête où chaque pièce représente une sous-requête imbriquée. En tant que data analyst, vous vous retrouvez à jongler avec des paires de sous-requêtes si imbriquées qu’elles finissent par ressembler à un plat de spaghettis. Vous perdez rapidement le fil de votre logique et le temps que vous passez à déboguer devient un véritable enfer. C’est là que les CTE entrent en jeu, offrant une clarté bien nécessaire.
Prenons un exemple concret. Imaginons que nous souhaitons obtenir les acteurs les mieux notés par genre à partir d’une base de données contenant des films, des acteurs et des notes. Utiliser des CTE nous permet de décomposer ce problème en plusieurs étapes logiques. Voici comment cela pourrait se présenter :
WITH ActorRatings AS (
SELECT actor_id, AVG(rating) as average_rating
FROM ratings
GROUP BY actor_id
),
BestActors AS (
SELECT actor_id, genre
FROM movies
JOIN ActorRatings ON movies.actor_id = ActorRatings.actor_id
WHERE average_rating > 8
)
SELECT * FROM BestActors;
Maintenant, si vous deviez écrire cela en utilisant des sous-requêtes imbriquées, cela pourrait tourner au outrage :
SELECT *
FROM (
SELECT actor_id, genre
FROM movies
WHERE actor_id IN (
SELECT actor_id
FROM ratings
GROUP BY actor_id
HAVING AVG(rating) > 8
)
) AS BestActorsSub;
On voit clairement que la première approche est beaucoup plus lisible. Les CTE permettent de nommer clairement chaque étape du processus, facilitant la maintenance et les mises à jour futures. Le débogage devient également un jeu d’enfant. Si une partie de votre CTE ne fonctionne pas, vous pouvez isoler la section concernée sans avoir à plonger dans des couches de sélection. Cela rend la vie bien plus facile lors des entretiens, où vous devez démontrer votre capacité à penser logiquement et clairement.
Pour faire un petit résumé, regarde ce tableau :
| Critères | CTE | Sous-requêtes |
|---|---|---|
| Lisibilité | Élevée | Basse |
| Performance | Variable selon le contexte | Peut être moins efficace |
| Complexité | Faible | Élevée |
En somme, malgré quelques débats sur leur performance dans certaines situations, les CTE sont clairement un atout quand il s’agit d’écrire des requêtes compréhensibles et faciles à maintenir. Car au final, comme disait Albert Einstein, “Tout devrait être aussi simple que possible, mais pas plus simple.” Si vous voulez approfondir ce sujet, n’hésitez pas à jeter un œil à ce lien intéressant ici.
Comment gérer efficacement les NULLs en SQL ?
Dans le monde impitoyable du SQL, le concept de NULL n’est pas qu’un simple caprice de la base de données. C’est l’absence de valeur, un trou noir qui matérialise l’incertitude. Contrairement à ce que certains pensent, NULL n’est pas égal à NULL. Si on essaie de l’utiliser ainsi, on se retrouve avec plus de mystères qu’on ne peut en résoudre. En fait, lorsqu’on veut vérifier la présence d’un NULL, on doit utiliser IS NULL ou IS NOT NULL.
Négliger ce principe, c’est ouvrir la porte à des résultats incomplets ou erronés. Imaginez une situation où vous devez joindre deux tables pour savoir combien d’interactions chaque client a eues. Si vous faites une jointure externe pleine (FULL OUTER JOIN) sans gérer les NULL, certains clients vont disparaître comme des fantômes, et vos rapports seront truffés d’erreurs. Car, que se passe-t-il lorsqu’un client n’a aucune interaction enregistrée ? La requête ne renverra pas de ligne, ou un NULL dans son absence d’interactions, si on ne s’en occupe pas correctement.
Utilisons un exemple concret pour illustrer cela. Supposons que nous avons une table des clients et une table des interactions. Si nous comptons les interactions tout en gérant les NULL, notre requête peut ressembler à ceci :
SELECT client_id,
COALESCE(COUNT(interaction_id), 0) AS total_interactions
FROM clients
LEFT JOIN interactions ON clients.id = interactions.client_id
GROUP BY client_id;
La fonction COALESCE est notre sauveur ici, remplaçant les NULL par une valeur plus sensée, zéro dans ce cas, garantissant que chaque client figure dans le rapport, même ceux qui n’ont eu aucune interaction. Saviez-vous qu’une étude de 2016 a révélé que plus de 80 % des erreurs de rapports proviennent de la mauvaise gestion des valeurs NULL ? (source : Expansai) C’est dire l’importance de maîtriser cette gestion.
En conclusion, bien gérer les NULL en SQL n’est pas un simple détail, c’est une nécessité pour produire des rapports fiables et exploitable. Prenez ce conseil au sérieux, car chaque NULL managé correctement vous rapproche un peu plus de la maîtrise de vos données.
Comment dédupliquer avec regroupement et conserver la ligne complète ?
Quand on aborde la question de déduplication avec regroupement en SQL, il est crucial de comprendre que le simple GROUP BY ne suffit pas toujours. On rêve tous d’obtenir une ligne entière qui représente le meilleur exemple d’un groupe, mais une requête de base peut rapidement nous piéger dans un marécage de données incomplètes. Imagine, par exemple, que tu veuilles identifier le meilleur produit vendu par mois, sans distinction d’année. Si tu utilises simplement GROUP BY, tu obtiendras peut-être un produit, mais pas tous les détails que tu veux.
Un cas classique d’erreur serait d’écrire une requête comme celle-ci :
SELECT product_id, MAX(sales) AS max_sales
FROM sales_data
GROUP BY month;
Avec cette approche, tu obtiens le produit qui a réalisé le meilleur chiffre d’affaires par mois, mais tu te retrouves avec seulement les product_id et le maximum des ventes. Tout autre détail lié au produit est perdu dans les limbes de ta base de données. Pas très pratique, hein ?
Pour résoudre ce souci, on se tourne vers des fonctions de classement comme ROW_NUMBER() ou RANK(). Ces fonctions te permettent de partitionner tes résultats en groupes et de leur appliquer un rang. Pour notre cas, la requête pourrait ressembler à ceci :
WITH RankedProducts AS (
SELECT product_id, sales, month,
RANK() OVER (PARTITION BY month ORDER BY sales DESC) AS sales_rank
FROM sales_data
)
SELECT product_id, sales, month
FROM RankedProducts
WHERE sales_rank = 1;
Cette requête fait le job. Elle classe d’abord les produits par mois selon leurs ventes et, en filtrant pour ne garder que ceux qui ont un rang de 1, tu obtiens une ligne complète pour le produit le plus vendu chaque mois. Magical, non ?
Cette technique est d’une importance capitale si tu veux éviter de jongler avec des données partielles ou incorrectes. Choisir la bonne méthode peut transformer une analyse banale en une révélation éclairante. Alors, la prochaine fois que tu te retrouves face à un problème de déduplication, n’oublie pas : grouper ne suffit pas, il te faut des outils adaptés comme RANK() pour tirer le meilleur parti de tes données. Pour aller plus loin dans l’apprentissage des requêtes SQL avancées, je te conseille de consulter cet article sur les exemples de requêtes SQL avancées.
Prêt à appliquer ces concepts SQL pour réussir vos entretiens data ?
Maîtriser ces six concepts SQL vous donne un avantage décisif en entretien data. Les fonctions fenêtre avec ordre, la distinction WHERE/HAVING, l’utilisation intelligente des auto-joins, la préférence pour les CTE, la gestion fine des NULLs et les techniques de déduplication permettent d’écrire des requêtes efficaces, précises et lisibles. En intégrant ces bonnes pratiques, vous évitez les pièges courants et gagnez en crédibilité technique. Résultat : une meilleure confiance face aux recruteurs et plus de chances de décrocher le poste.
FAQ
Pourquoi ORDER BY est-il obligatoire dans les fonctions fenêtre SQL ?
Quelle est la différence entre WHERE et HAVING en SQL ?
Quand utiliser un auto-joint en SQL ?
Pourquoi privilégier les CTE aux sous-requêtes imbriquées ?
Comment gérer les NULL efficacement en SQL ?
A propos de l’auteur
Franck Scandolera est consultant expert en data, formateur et Analytics Engineer avec plus de dix ans d’expérience dans le data engineering, SQL, automatisation et IA générative. Responsable de l’agence webAnalyste et formateur reconnu, il accompagne les professionnels sur l’utilisation avancée de SQL et l’infrastructure data. Découvrez son parcours et expertises sur Franck Scandolera.
⭐ Analytics engineer, Data Analyst et Automatisation IA indépendant ⭐
- Ref clients : Logis Hôtel, Yelloh Village, BazarChic, Fédération Football Français, Texdecor…
Mon terrain de jeu :
- Data Analyst & Analytics engineering : tracking avancé (GTM server, e-commerce, CAPI, RGPD), entrepôt de données (BigQuery, Snowflake, PostgreSQL, ClickHouse), modèles (Airflow, dbt, Dataform), dashboards décisionnels (Looker, Power BI, Metabase, SQL, Python).
- Automatisation IA des taches Data, Marketing, RH, compta etc : conception de workflows intelligents robustes (n8n, App Script, scraping) connectés aux API de vos outils et LLM (OpenAI, Mistral, Claude…).
- Engineering IA pour créer des applications et agent IA sur mesure : intégration de LLM (OpenAI, Mistral…), RAG, assistants métier, génération de documents complexes, APIs, backends Node.js/Python.





