SQL interview questions data engineers actually get.
Warm-up: the five you must nail
If you can't answer these cold, don't book the interview yet. They're the baseline every screen checks.
- Difference between
INNER,LEFT,FULL OUTER, andCROSS JOIN. When does aLEFT JOINsilently drop rows? (Answer: it doesn't — but aWHEREon the right table turns it into an inner join.) WHEREvsHAVINGvsQUALIFY. Order of evaluation. WhyWHEREcan't reference an aggregate.- How does
GROUP BYhandle NULLs? (They form their own group.) How do aggregates handle NULLs? (Skipped, exceptCOUNT(*).) - Difference between
UNIONandUNION ALL. Which one costs a sort + distinct? Which one do you almost always want in a pipeline? - What does
COUNT(*)vsCOUNT(column)vsCOUNT(DISTINCT column)return? One-line answers.
Window functions (expect at least one)
Windows are the single most-asked SQL topic in DE interviews. Know the shape without looking it up.
- Find the 2nd highest salary per department.
DENSE_RANK() OVER (PARTITION BY dept ORDER BY salary DESC) = 2. Say whyDENSE_RANKoverRANKoverROW_NUMBER— ties matter. - Top-N per group. Same pattern with
ROW_NUMBER. Filter in an outer query or withQUALIFY. - 7-day rolling average of daily active users.
AVG(dau) OVER (ORDER BY day RANGE BETWEEN INTERVAL '6' DAY PRECEDING AND CURRENT ROW). Trap: days with zero events don't exist in the table — generate a date spine first. - Cumulative sum of revenue per customer.
SUM(amount) OVER (PARTITION BY customer_id ORDER BY order_date ROWS UNBOUNDED PRECEDING). - Previous-row diff (day-over-day change).
value - LAG(value) OVER (ORDER BY day). - Percent of total per partition.
amount / SUM(amount) OVER (PARTITION BY category). - Difference between
ROWSandRANGEframes.ROWScounts physical rows;RANGEcounts logical values (ties collapse). Ask when it matters.
Gaps-and-islands (the pattern that separates candidates)
The pattern for sessionization, streak detection, and "consecutive days" problems. Master one template — it solves them all.
- Split events into sessions with a 30-min inactivity gap. Flag a new session when
event_time - LAG(event_time) OVER (PARTITION BY user ORDER BY event_time) > INTERVAL '30' MINUTE, then running-sum the flag. - Find the longest login streak per user. Row-number by date, subtract from date → constant per island. Group by that constant, take
MAX(COUNT(*)). - Find users who logged in 3 days in a row. Same island trick, filter islands with
COUNT(*) >= 3. - Merge overlapping time ranges per resource. Track running max of end-time, start a new island when a start > max end so far.
Deduplication & correctness
- Keep the latest row per key.
QUALIFY ROW_NUMBER() OVER (PARTITION BY id ORDER BY updated_at DESC) = 1. Trap: what ifupdated_atties? Add a tiebreaker (id, ingestion time) — otherwise output is non-deterministic. - Find exact duplicates.
GROUP BY every_column HAVING COUNT(*) > 1— orROW_NUMBERand keep rows where n > 1. - How would you catch a silent duplication bug in a daily pipeline? Data-quality test on unique key:
COUNT(*) = COUNT(DISTINCT pk). dbtuniquetest or a hand-rolled assertion. - You joined two tables and row count exploded — what went wrong? Non-unique join key on one side (fan-out). Aggregate first, then join.
Aggregation & data modeling puzzles
- Given
orders(user_id, order_date, amount), compute month-over-month revenue growth. Aggregate to month, useLAG, compute(cur - prev) / prev. - Compute customer retention: users who ordered in month N AND month N+1. Self-join monthly buckets or use array/set intersection functions.
- Compute daily active users, weekly active users, monthly active users from an events table. Three
COUNT(DISTINCT user_id)queries with different date bucketing. Discuss the DAU/MAU ratio (stickiness). - Pivot: turn one-row-per-event into one-row-per-user with columns per event type.
MAX(CASE WHEN event = 'X' THEN 1 END)per column, or dialect-specificPIVOT. - Unpivot: turn wide columns into long rows.
UNION ALLper column, orUNPIVOT/CROSS JOIN LATERAL.
Performance & scale (senior signal)
Any answer that reasons about IO, partitioning, and skew separates a mid from a senior candidate.
- Your query is slow — how do you diagnose it? Read the query plan first: what's the largest scan, where's the biggest shuffle, what's the join order? Only then talk about indexes or partitions.
- When does a subquery beat a window function (and vice versa)? Correlated subqueries are killers at scale; windows scan the partition once. Prefer windows unless the subquery filters the outer set dramatically first.
- How do you avoid a shuffle on a warehouse like Snowflake or BigQuery? Cluster/partition by the join or filter key. Aggregate before joining. Broadcast small tables.
- Column pruning and predicate pushdown — why do they matter for Parquet/Iceberg? Only relevant columns and partitions are read from object storage. A
SELECT *across a wide table can cost 20× a targeted select. - Explain data skew in a group-by or join. One key with 90% of rows sends everything to one worker. Fix with salting, two-stage aggregation, or a skew-hint.
Live SQL: how to actually pass the round
- Restate the problem in your own words before writing anything. Confirm inputs, outputs, edge cases.
- Ask about NULLs, duplicates, and time zones — most trap questions hide there.
- Write CTEs top-down, not one giant query. Name each step. Interviewers grade readability.
- Say "I'd add a data-quality check here" when you make an assumption. Free senior points.
- If stuck, verbalize the shape of the answer ("I need one row per user per day, then rank, then filter"). They'd rather help you than watch you type in silence.
Practice on DataForge
The SQL & warehousing courses drill windows, gaps-and-islands, and dbt patterns with exercises graded on the exact traps above. Bug Hunt ships broken queries and pipelines — you fix them and see the tests go green. If you can complete both, these interview questions become one-line answers instead of five-minute stumbles.
FAQ
- What SQL topics show up most in data engineering interviews?
- Window functions (ROW_NUMBER, RANK, LAG/LEAD, running aggregates), self-joins, gaps-and-islands, deduplication, date bucketing, and CTEs. If you're rock-solid on those five, you'll pass 80% of screens.
- How hard are SQL interview questions for data engineers vs analysts?
- Data engineering interviews go deeper on performance, correctness at scale, and edge cases (NULLs, duplicates, late-arriving data). Analyst rounds care more about business framing. Same syntax, different expectations.
- Do I need to memorize every SQL function?
- No. Memorize the shape of window functions, join types, and CTE patterns. Everything else — string funcs, date funcs — you can reason from first principles or ask about.
- How should I practice SQL for interviews?
- Solve problems out loud on a whiteboard or empty editor — no autocomplete. Explain your join keys, your NULL handling, and why you picked a window over a subquery. Interviewers grade reasoning, not syntax.
- What SQL dialect do interviewers use?
- Most use ANSI-ish SQL and don't care about dialect. If they use Snowflake/BigQuery/Postgres specifics (QUALIFY, ARRAY_AGG, LATERAL), they'll say so — otherwise stick to portable syntax.
- How long should I prepare SQL specifically?
- One to two weeks if your fundamentals are decent. Do 3-5 problems a day, focused on windows and gaps-and-islands. Volume matters less than reviewing your own reasoning after each one.
Ready to start?
7 days free. Then less than a coffee per month.
Practice with the courses- No credit card for the trial
- Cancel anytime
- 300+ exercises
- 14 full courses