En entretien data, six concepts SQL cruciaux sont souvent mal maîtrisés, compromettant vos chances. Comprendre les fonctions window, les agrégats, les jointures, les CTEs, la gestion des NULLs et la déduplication est vital. Découvrez comment corriger ces erreurs fréquentes avec des exemples probants.
3 principaux points à retenir.
- Fenêtres analytiques : toujours spécifier ORDER BY dans fonctions comme LAG()
- Filtres sur agrégats : WHERE ne supporte pas les fonctions d’agrégation, préférez HAVING
- Déduplication : utiliser ROW_NUMBER() ou RANK() pour sélectionner la meilleure ligne par groupe
Pourquoi les fonctions window posent-elles problème
Les fonctions window en SQL, comme LAG() et LEAD(), peuvent laisser perplexes bon nombre de professionnels, surtout lorsqu’elles sont apprises par cœur sans comprendre les subtilités du frame, de la partition ou de l’importance de ORDER BY. Parfois, ce manque de clarté peut mener à des résultats aberrants. Alors, pourquoi l’usage de ORDER BY est-il si crucial dans ces contextes ? La réponse est simple : il garantit une cohérence temporelle et permet d’obtenir des résultats déterministes.
Prenons un exemple concret. Supposons que nous avons une table achats qui contient des user_id et des date_achats :
user_id | date_achat
---------|------------
1 | 2023-02-01
1 | 2023-02-05
1 | 2023-03-01
2 | 2023-02-02
2 | 2023-02-07
Si nous voulons utiliser LAG() pour obtenir la date de l’achat précédent d’un utilisateur, voici comment cela pourrait être problématique sans ORDER BY :
SELECT user_id,
date_achat,
LAG(date_achat) OVER (PARTITION BY user_id) AS date_achat_precedent
FROM achats;
Sans ORDER BY, la PostgreSQL ne sait pas dans quel ordre les dates doivent être examinées. Cela peut produire des résultats complètement aléatoires ! Maintenant, corrigeons cela :
SELECT user_id,
date_achat,
LAG(date_achat) OVER (PARTITION BY user_id ORDER BY date_achat) AS date_achat_precedent
FROM achats;
Cette requête assure que nous examinons les dates d’achats dans l’ordre chronologique pour chaque utilisateur. Les résultats deviennent alors cohérents et logiques. Classiquement, voici quelques erreurs que l’on voit souvent avec les fonctions window :
- Oublier ORDER BY : Comme démontré, cela peut mener à des résultats incohérents.
- Ne pas utiliser PARTITION BY : Cela fait que les calculs sont faits sur l’ensemble de la table au lieu d’être segmentés par groupe d’intérêt.
- Confondre les fonctions de window et d’agrégation : Ces deux types de fonctions répondent à des logiques complètement différentes.
En comprenant bien chaque élément d’une fonction window, vous éviterez ces pièges. Ne laissez pas votre SQL vous jouer des tours ! Pour plus de détails sur les pièges courants en SQL, vous pouvez consulter cette ressource.
Comment filtrer correctement avec des fonctions d’agrégation
Quand on parle de filtrage avec SQL, on touche à un concept fondamental : l’ordre d’exécution des requêtes. Commencez par bien comprendre que la clause WHERE intervient avant l’agrégation des données. Cette nuance cruciale fait toute la différence. Parce que oui, on ne peut pas utiliser des fonctions d’agrégation comme MIN() ou SUM() au sein d’un WHERE. C’est pour cette raison qu’on fait appel à HAVING, qui vient jouer son rôle après l’agrégation des données.
Pour illustrer cela, prenons un exemple terre à terre. Supposons qu’on souhaite analyser le chiffre d’affaires par producteur de vin et qu’on veuille filtrer ceux dont la note minimale est, disons, 85. Avec HAVING, ça se passe comme ça :
SELECT producteur, SUM(chiffre_affaires) AS total_affaire
FROM ventes
GROUP BY producteur
HAVING MIN(note) >= 85;
D’un autre côté, voici comment cela n’aurait pas fonctionné avec WHERE :
SELECT producteur, SUM(chiffre_affaires) AS total_affaire
FROM ventes
WHERE MIN(note) >= 85
GROUP BY producteur;
En parlant d’ordre d’exécution, voici un schéma simplifié :
Étapes |
---|
FROM |
WHERE |
GROUP BY |
HAVING |
SELECT |
ORDER BY |
C’est cet ordre qui confère à votre requête le pouvoir de renvoyer les résultats escomptés. N’oubliez jamais de garder cela à l’esprit lors de vos entretiens : une mauvaise utilisation de WHERE et HAVING peut vous faire perdre des points, et dans un environnement compétitif, chaque détail compte.
Les bases du SQL peuvent apparaître ennuyeuses à première vue, mais elles sont essentielles pour faire des analyses de données poussées. Si vous avez besoin d’un rappel ou de vous plonger plus en profondeur dans le sujet, ce lien peut vous guider : SQL pour l’analyse de données.
Quand et comment utiliser les self-joins efficacement
Tu veux comparer des événements dans une même table, par exemple des taux de change à deux dates différentes ? Alors, laisse-moi te parler de l’astuce qu’est la self-join. En gros, c’est le moyen efficace pour faire des comparaisons sans se perdre dans la complexité des sous-requêtes imbriquées qui rendent souvent le tout aussi lisible qu’un brouillon bourré de ratures.
Imagine une table appelée taux_de_change qui contient trois colonnes : date, devise et taux. Disons que tu veux comparer le taux de change d’une devise à deux dates différentes. Utiliser une self-join va te permettre de le faire en une seule requête, claire et concise.
SELECT
a.date AS date_1,
a.taux AS taux_1,
b.date AS date_2,
b.taux AS taux_2
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-15';
Avec cette requête, tu peux facilement obtenir les taux de change pour la même devise à deux dates précises. Si tu avais opté pour une sous-requête, cela aurait impliqué des couches de complexité inutiles. Quelqu’un pourrait croire à tort que plus on complique, mieux c’est. Faux ! Lors des entretiens, cette clarté et cette performance d’exécution sont souvent jugées. Rappelle-toi de cette phrase de Confucius : « La simplicité est la sophistication suprême. » En SQL, cela se traduit par des self-joins.
Pour finir, maîtriser la self-join n’est pas juste un « plus » dans ta boîte à outils, c’est un must ! Cela te permet d’optimiser à la fois les performances de tes requêtes et la clarté de ton code. L’objectif est d’avoir non seulement des résultats efficaces, mais aussi compréhensibles. Tu veux voir un exemple en vidéo ? Regarde juste ici pour te plonger dans l’univers fascinant du SQL.
Pourquoi préférer les CTEs aux subqueries multiples
Quand il s’agit de structurer vos requêtes SQL, vous êtes confronté à un choix : utiliser des subqueries imbriquées ou opter pour des Common Table Expressions (CTEs). La réponse peut sembler évidente avec le bon éclairage. Les subqueries, avec leur style d’imbrication, peuvent rapidement devenir des monstres illisibles et imprévisibles. Imaginez une requête qui tente d’extraire des informations avec cinq niveaux de sous-requêtes. Vous voyez le tableau : une spirale de complexité qui met vos compétences en lisibilité à l’épreuve, entourée d’un halo de doutes pour quiconque tentant de la déchiffrer plus tard.
Pour illustrer cela, prenons un exemple où nous cherchons à obtenir le rang des employés en fonction de leurs performances, en utilisant des sous-requêtes classiques. Voici comment cela pourrait se présenter :
SELECT emp_name,
salary,
(SELECT COUNT(*)
FROM employees e2
WHERE e2.performance > e1.performance) AS rank
FROM employees e1
WHERE (SELECT COUNT(*)
FROM employees e3
WHERE e3.department_id = e1.department_id) > 1;
On est d’accord, ça pique un peu. La complexité, l’illogisme, et un coup de fatigue pour bien des lecteurs. Avec cinq niveaux de ces monstres imbriqués, même vous voudriez avoir un double expresso pour vous réveiller avant de plonger là-dedans.
À ce stade, vous pourriez vous poser une question : pourquoi se battre avec ça quand on peut faire simple ? Voici la même logique mais cette fois avec des CTEs :
WITH ranked_employees AS (
SELECT emp_name,
salary,
DENSE_RANK() OVER (ORDER BY performance DESC) AS rank
FROM employees
),
filtered_employees AS (
SELECT *
FROM ranked_employees
WHERE department_id IN (SELECT department_id FROM departments)
)
SELECT *,
COUNT(*) OVER (PARTITION BY department_id) AS department_count
FROM filtered_employees;
Regardez comme c’est clair ! Chaque CTE est un petit morceau de logique, des noms explicites qui parlent d’eux-mêmes. En réduisant la profondeur d’imbrication, la requête devient beaucoup plus lisible et surtout, bien plus facile à maintenir. La maintenabilité ne devrait pas être un défi. Moins de complexité signifie moins d’erreurs potentielles lors des débogages. Qui ne se réjouirait pas de pouvoir passer l’aspirateur dans son code, au lieu d’excaver d’anciennes couches d’une logique opaque ? En SQL, la simplicité est reine.
En résumé, pour toutes vos futures requêtes, gardez à l’esprit ce principe : la lecture, la maintenabilité et le débogage sont des alliés puissants. Choisissez la voie claire des CTEs, vous ne le regretterez pas.
Comment gérer correctement les valeurs NULL en SQL
Quand on parle de SQL, un concept qui mérite une attention particulière est celui des valeurs NULL. Imaginez-vous en entretien, en train de discuter d’une requête, et soudain le recruteur vous interroge sur NULL. Que lui répondez-vous ? La première règle d’or ici, c’est que NULL n’est jamais égal à quelque chose, même pas à NULL. Par conséquent, essayer de faire une comparaison comme = NULL
est une erreur logique. Une vraie passoire pour vos résultats.
Prenons un exemple concret. Supposons que vous ayez une table Clients et une table Commandes. Si certains ID clients de la table Clients sont NULL lors d’une jointure extérieure, ces lignes vont fausser complètement votre agrégation de données. Imaginez que vous essayez de faire un compte des commandes par client : si un client n’a pas d’ID assigné, comment le compteriez-vous ? Le résultat ne sera pas seulement erroné, il pourrait également entraîner de fausses conclusions quant à l’activité de votre entreprise.
Pour gérer les NULL avec brio, vous pouvez utiliser la fonction COALESCE(). Cette fonction vous permet de remplacer une valeur NULL par une valeur par défaut. Prenons un exemple simple : si vous avez un compteur qui doit afficher le nombre de commandes passées par chaque client, mais que certains clients n’ont passé aucune commande (NULL), vous pouvez remplacer ces NULL par zéro.
SELECT c.client_id, COUNT(o.order_id) AS total_commandes
FROM Clients c
LEFT JOIN Commandes o ON c.client_id = o.client_id
GROUP BY c.client_id
HAVING COALESCE(total_commandes, 0) > 0;
Dans l’exemple ci-dessus, on s’assure que les clients sans commande apparaissent avec zéro, et non comme NULL. Ce faisant, on évite de fausser l’analyse des données.
Pour résumer, voici un tableau des conditions logiques concernant NULL :
- NULL = NULL ➜ Faux
- NULL < 1 ➜ Faux
- NULL > 1 ➜ Faux
- COALESCE(NULL, valeur) ➜ valeur
En maîtrisant le concept de NULL, vous êtes déjà en train de bâtir une base solide pour vos réponses en entretien. Pour plus de détails sur la gestion des données manquantes, n’hésitez pas à consulter cet article ici.
Quelle méthode pour déduplication par groupe sans erreur
Un des premiers réflexes en SQL peut être de vouloir utiliser GROUP BY pour dédupliquer les données. C’est tentant, non ? Le concept semble simple : grouper par une colonne pour obtenir un ensemble de résultats. Mais voilà, ça ne suffit pas si l’on souhaite conserver l’intégralité des informations d’une ligne, comme la meilleure vente par mois. La réalité, c’est que GROUP BY ne fournit que des lignes agrégées, et souvent, on perd une bonne partie de ce qui nous intéresse.
Un piège courant est d’ajouter une clause LIMIT 1, avec l’espoir d’obtenir la première ligne de chaque groupe. Mauvaise idée ! LIMIT ne fonctionne pas par groupe, mais globalement. Ainsi, vous n’obtiendrez pas la ligne que vous cherchez, mais juste un échantillon du jeu de données. Frustrant, n’est-ce pas ?
Heureusement, SQL offre des outils plus puissants. Utilisons les fonctions window comme ROW_NUMBER() ou RANK() qui peuvent faire le travail. Ces fonctions permettent de partitionner les données pour chaque groupe et de les ordonner selon notre critère de sélection. Prenons un exemple concret pour illustrer cela. Supposons que nous avons une table ventes avec les colonnes mois, produit et montant. Nous voulons trouver la meilleure vente par mois.
SELECT mois, produit, montant
FROM (
SELECT mois, produit, montant,
RANK() OVER (PARTITION BY mois ORDER BY montant DESC) AS rank
FROM ventes
) AS ranked_sales
WHERE rank = 1;
Dans ce code, nous partitionnons les données par mois et ordonnons les lignes par montant en ordre décroissant. Ensuite, nous filtrons pour ne garder que celles ayant un rank égal à 1, c’est-à-dire la meilleure vente. Souvenez-vous, les fonctions Window sont vos alliées pour la déduplication et la conservation des informations essentielles.
Pour compléter, voici un tableau comparatif des méthodes de déduplication :
Méthode | Avantages | Inconvénients |
---|---|---|
GROUP BY | Simplicité d’utilisation | Perte d’informations |
LIMIT 1 | Rapidité | Non régi par groupe |
ROW_NUMBER() / RANK() | Conserve les données complètes | Complexité des requêtes |
La clé est d’apprendre à bien utiliser ces fonctions pour éviter les faux pas lors de vos entretiens en data. Si vous vous intéressez aux subtilités de la déduplication, vous pouvez aussi consulter des discussions comme celle-ci sur Reddit.
Prêt à maîtriser ces concepts pour réussir vos entretiens SQL ?
Maîtriser ces six concepts SQL est non négociable pour sortir du lot en entretien data. Que ce soit la subtilité des fonctions window, le maniement des agrégats avec HAVING, ou la gestion des NULLs, chacun de ces points conditionne un résultat fiable et lisible. En intégrant ces bonnes pratiques, vous décuplerez vos chances d’impressionner les recruteurs et de passer à la prochaine étape. Bref, un investissement technique qui paie cash lors de vos entretiens où chaque ligne de code compte.
FAQ
Pourquoi faut-il toujours utiliser ORDER BY avec les fonctions window ?
Quelle différence clé entre WHERE et HAVING ?
Quand utiliser une self-join en SQL ?
Pourquoi privilégier les CTEs aux subqueries imbriquées ?
Comment gérer les valeurs NULL efficacement en SQL ?
A propos de l’auteur
Franck Scandolera, responsable de l’agence webAnalyste et formateur expert en Data Engineering, Web Analytics et SQL, accompagne depuis plus de dix ans professionnels et entreprises dans la maîtrise de leurs données. Spécialisé en automatisation et intégration de pipelines data, il transmet un savoir pragmatique, alliant rigueur technique et applications concrètes pour réussir dans les environnements data compétitifs.