Guide recrutement data
Test technique SQL pour la data : ce qu'on évalue vraiment en entretien
SQL reste le langage central de la data. Mais « savoir faire du SQL » va d'un SELECT ... WHERE à une requête analytique avec fenêtres imbriquées et diagnostic de performance. Voici comment mesurer l'écart réel.
Data Builder·Juillet 2025·10 min de lecture·Data Analyst / Analytics Engineer
SQL est le meilleur prédicteur global du niveau data : un profil solide en SQL l'est presque toujours ailleurs. En entretien, l'écart se creuse vite entre celui qui écrit un GROUP BY et celui qui raisonne sur un plan d'exécution. Voici les cinq dimensions que nous évaluons.
1Agrégations et GROUP BY
Question discriminante
Quelle est la différence entre WHERE et HAVING, et quand utiliser l'un ou l'autre ?
WHERE filtre les lignes avant l'agrégation ; HAVING filtre après, sur le résultat d'un agrégat.- Agrégats conditionnels :
CASE dans SUM, ou COUNT(*) FILTER (WHERE ...). - Extensions
GROUPING SETS, ROLLUP, CUBE pour des sous-totaux en une passe. - Pièges des
NULL dans les agrégats (COUNT(col) ignore les NULL, pas COUNT(*)).
Signal d'alerte : un candidat qui met une condition d'agrégat dans le WHERE (ou qui confond WHERE et HAVING) révèle une compréhension de surface.
2Jointures
Question discriminante
Décrivez les types de jointures, et donnez un cas où une LEFT JOIN change le résultat d'un COUNT.
INNER / LEFT / RIGHT / FULL — savoir laquelle conserve les lignes non appariées.- Anti-jointure (
LEFT JOIN ... WHERE b.id IS NULL) pour « ce qui n'existe pas en face ». - Auto-jointure pour comparer des lignes d'une même table (hiérarchies, doublons).
- Le fan-out : une jointure 1-N qui duplique les lignes et double les montants sommés.
Signal d'alerte : ne pas repérer qu'une jointure 1-N gonfle un SUM est une erreur qui fausse des rapports en production.
3Fonctions fenêtre
Question discriminante
QUALIFY est au PARTITION BY ce que HAVING est au GROUP BY. Expliquez.
SELECT client_id, order_id, amount,
ROW_NUMBER() OVER (PARTITION BY client_id
ORDER BY order_date DESC) AS rn
FROM orders
QUALIFY rn = 1
- Classement :
ROW_NUMBER (unique), RANK (saute), DENSE_RANK (ne saute pas). - Décalage :
LAG/LEAD pour comparer à la ligne précédente/suivante. - Cumuls :
SUM() OVER (ORDER BY ...) ; cadre ROWS BETWEEN pour moyennes mobiles. QUALIFY filtre sur une fonction fenêtre sans sous-requête (BigQuery, Snowflake, DuckDB).
4Lecture de requête et esprit critique
Question discriminante
On vous donne une requête et un résultat surprenant. Comment procédez-vous avant de conclure ?
- Lire le résultat et la donnée : un
COUNT qui sur-compte trahit souvent un fan-out. - Distinguer un vrai signal d'un écart non significatif (bruit) avant de recommander.
- Vérifier les
NULL, les doublons et la granularité de la table. - Reformuler l'intention métier de la requête, pas seulement sa syntaxe.
Signal d'alerte : prendre un chiffre agrégé pour argent comptant, sans le questionner, est un signal faible caractéristique.
5Performance
Question discriminante
Une requête est lente sur un gros volume. Par quoi commencez-vous ?
- Lire le plan d'exécution (
EXPLAIN) : scans, jointures, tris coûteux. - Réduire la donnée lue : éviter
SELECT *, filtrer tôt, prédicats sargables. - Index / clustering / partitionnement adaptés au filtre et à la jointure.
- Sur les entrepôts colonnes (BigQuery, Snowflake) : penser en colonnes scannées et coût, pas en index.
6Grille par niveau
| Niveau | Maîtrise attendue | Signal GO | NO-GO |
|---|
| Junior | SELECT, WHERE, GROUP BY, jointures simples | Écrit un GROUP BY correct, explique WHERE vs HAVING | Met une condition d'agrégat dans le WHERE |
| Confirmé | Fonctions fenêtre, CTE, anti-jointures, agrégats conditionnels | Écrit un top-N par groupe, repère un fan-out | Ne sait pas différencier ROW_NUMBER, RANK, DENSE_RANK |
| Senior | Optimisation, plans d'exécution, Pareto/cumuls, QUALIFY | Lit un plan, questionne un résultat surprenant | Prend un chiffre agrégé pour argent comptant |
| Lead | Modélisation, conventions, coûts à l'échelle | Arbitre coût/perf, fixe des standards d'équipe | Ne peut pas expliquer pourquoi une requête est lente |
Home›Blog›SQL technical interview for data
Data hiring guide
SQL technical interview for data: what we really assess
SQL is still the core language of data. But ‘knowing SQL’ ranges from a SELECT ... WHERE to an analytical query with nested windows and performance diagnosis. Here's how to measure the real gap.
Data Builder·July 2025·10 min read·Data Analyst / Analytics Engineer
SQL is the best overall predictor of data level: a profile strong in SQL almost always is elsewhere too. In an interview, the gap widens fast between someone who writes a GROUP BY and someone who reasons about an execution plan. Here are the five dimensions we assess.
1Aggregations and GROUP BY
Key question
What is the difference between WHERE and HAVING, and when do you use each?
WHERE filters rows before aggregation; HAVING filters after, on an aggregate result.- Conditional aggregates:
CASE inside SUM, or COUNT(*) FILTER (WHERE ...). GROUPING SETS, ROLLUP, CUBE extensions for subtotals in one pass.NULL traps in aggregates (COUNT(col) skips NULLs, COUNT(*) doesn't).
Warning signal : a candidate who puts an aggregate condition in WHERE (or confuses WHERE and HAVING) reveals surface understanding.
2Joins
Key question
Describe the join types, and give a case where a LEFT JOIN changes the result of a COUNT.
INNER / LEFT / RIGHT / FULL — knowing which keeps unmatched rows.- Anti-join (
LEFT JOIN ... WHERE b.id IS NULL) for ‘what has no match’. - Self-join to compare rows of the same table (hierarchies, duplicates).
- Fan-out: a 1-N join that duplicates rows and doubles summed amounts.
Warning signal : failing to spot that a 1-N join inflates a SUM is a mistake that corrupts production reports.
3Window functions
Key question
QUALIFY is to window functions what HAVING is to GROUP BY. Explain.
SELECT client_id, order_id, amount,
ROW_NUMBER() OVER (PARTITION BY client_id
ORDER BY order_date DESC) AS rn
FROM orders
QUALIFY rn = 1
- Ranking:
ROW_NUMBER (unique), RANK (skips), DENSE_RANK (doesn't skip). - Offset:
LAG/LEAD to compare to the previous/next row. - Running totals:
SUM() OVER (ORDER BY ...); ROWS BETWEEN frame for moving averages. QUALIFY filters on a window function without a subquery (BigQuery, Snowflake, DuckDB).
4Query reading and critical thinking
Key question
You're given a query and a surprising result. What do you do before concluding?
- Read the result and the data: a
COUNT that over-counts often reveals a fan-out. - Tell a real signal from a non-significant difference (noise) before recommending anything.
- Check
NULLs, duplicates and the table granularity. - Restate the business intent of the query, not just its syntax.
Warning signal : taking an aggregate figure at face value, without questioning it, is a characteristic weak signal.
5Performance
Key question
A query is slow on a large volume. Where do you start?
- Read the execution plan (
EXPLAIN): scans, joins, costly sorts. - Reduce data read: avoid
SELECT *, filter early, sargable predicates. - Indexes / clustering / partitioning matching the filter and join.
- On columnar warehouses (BigQuery, Snowflake): think in scanned columns and cost, not indexes.
6Level grid
| Level | Expected proficiency | Signal GO | NO-GO |
|---|
| Junior | SELECT, WHERE, GROUP BY, simple joins | Writes a correct GROUP BY, explains WHERE vs HAVING | Puts an aggregate condition in WHERE |
| Mid-level | Window functions, CTEs, anti-joins, conditional aggregates | Writes a top-N per group, spots a fan-out | Can't tell ROW_NUMBER, RANK, DENSE_RANK apart |
| Senior | Optimization, execution plans, Pareto/running totals, QUALIFY | Reads a plan, questions a surprising result | Takes an aggregate figure at face value |
| Lead | Modelling, conventions, cost at scale | Balances cost/perf, sets team standards | Can't explain why a query is slow |