SQL Interview Speed Drills: Solve 3 to 5 Questions in 30 Minutes

SQL Updated 六月 29, 2026 9 mins read Leon Leon
SQL Interview Speed Drills: Solve 3 to 5 Questions in 30 Minutes cover image

Quick summary

Summarize this blog with AI

Introduction

A timed SQL interview is not the same as ordinary SQL practice. In normal practice, you can reread the prompt, chase a syntax error, rewrite the query from scratch, and check the answer at your own pace. In a 25 to 30 minute screen, you may need to solve three to five prompts while explaining your thinking. That changes the skill being tested.

The hard part is usually not a rare SQL function. The hard part is switching quickly from question to question without losing the grain, joining at the wrong level, overbuilding the first solution, or spending eight minutes polishing a query that only needed a clear first pass.

This guide gives you a repeatable timed practice routine. Use it when you already know the basics - joins, GROUP BY, CTEs, CASE, dates, and window functions - but you need to answer faster and with fewer silent mistakes.

What a 30-minute SQL round is really testing

Short SQL rounds reward fluency, but they also test judgment. The interviewer wants to see whether you can turn business language into reliable data logic under pressure. A strong answer usually shows five things:

  • You identify the grain. You know whether one output row should represent a customer, order, day, product, session, or event.
  • You choose the base table quickly. You start from the table that naturally represents the thing being counted or ranked.
  • You control joins. You notice one-to-many relationships before they inflate counts or revenue.
  • You use the simplest sufficient pattern. You do not reach for a window function when grouped aggregation is enough, and you do not force everything into one nested query.
  • You test edge cases out loud. You mention NULLs, ties, duplicate rows, missing dates, or users with no activity when they matter.

The goal is not to type like a competitive programmer. The goal is to make fewer expensive decisions per question.

The time budget

Use a visible timer when you practice. A 30-minute round with three questions has a different rhythm from a five-question speed screen.

Round type Target pace How to behave
3 questions in 30 minutes 8 minutes per question, 6 minutes buffer Clarify the metric, write a clean solution, and explain one edge case.
4 questions in 30 minutes 6 minutes per question, 6 minutes buffer Use known patterns. Avoid unnecessary refactors after the query is correct.
5 questions in 30 minutes 5 minutes per question, 5 minutes buffer Prioritize a correct core query. Say assumptions briefly and move on.

If you regularly exceed these budgets, do not just "practice more." Look at where time is leaking: prompt reading, choosing the base table, remembering syntax, debugging joins, or testing the final answer.

The 60-second opening routine

Before writing SQL, spend one minute forcing the problem into a small shape. This prevents most slow rewrites.

  1. Restate the output. "We need one row per customer with total completed order revenue."
  2. Name the grain. "The final grain is customer."
  3. Pick the base table. "Orders is the base because revenue lives there."
  4. Mark filters. "Completed orders only, date range in 2026, exclude test accounts if the users table has that flag."
  5. Name the pattern. Aggregation, anti-join, latest row, top-N, date bucket, rolling metric, or deduplication.

In an interview, saying this out loud helps the interviewer follow you. In practice, write it as a short comment above the query.

Five speed patterns to drill

Most short SQL screens are built from a small set of patterns. You should be able to recognize these before your hands start typing.

1. Grouped metric

Use this when the question asks for totals, averages, counts, rates, or revenue by a dimension.

-- One row per customer: completed order count and revenue
SELECT
  o.customer_id,
  COUNT(*) AS completed_orders,
  SUM(o.order_total) AS completed_revenue
FROM orders o
WHERE o.status = 'completed'
GROUP BY o.customer_id;

Speed check: if you join to another table, ask whether that table has one row per customer or many rows per customer. If it has many, pre-aggregate before joining.

2. Latest row per entity

Use this for most recent order, latest subscription state, current job title, last login, or most recent ticket.

WITH ranked_events AS (
  SELECT
    e.*,
    ROW_NUMBER() OVER (
      PARTITION BY e.user_id
      ORDER BY e.event_time DESC, e.event_id DESC
    ) AS rn
  FROM events e
)
SELECT *
FROM ranked_events
WHERE rn = 1;

Speed check: include a deterministic tie-breaker. If two events have the same timestamp, the query should still return the same row every time.

3. Top-N per group

Use this when the prompt says top products per category, highest spending users per month, most active accounts per region, or top movies per genre.

WITH product_revenue AS (
  SELECT
    p.category,
    oi.product_id,
    SUM(oi.quantity * oi.unit_price) AS revenue
  FROM order_items oi
  JOIN products p
    ON p.product_id = oi.product_id
  GROUP BY p.category, oi.product_id
),
ranked AS (
  SELECT
    product_revenue.*,
    DENSE_RANK() OVER (
      PARTITION BY category
      ORDER BY revenue DESC
    ) AS revenue_rank
  FROM product_revenue
)
SELECT *
FROM ranked
WHERE revenue_rank <= 3;

Speed check: decide whether ties should be included. Use ROW_NUMBER for exactly N rows per group, RANK or DENSE_RANK when ties matter.

4. Missing or inactive entities

Use this when the question asks for customers with no orders, products never purchased, users who did not log in, or accounts with zero activity.

SELECT
  c.customer_id,
  c.created_at
FROM customers c
LEFT JOIN orders o
  ON o.customer_id = c.customer_id
  AND o.status = 'completed'
WHERE o.order_id IS NULL;

Speed check: keep right-table filters inside the ON clause when you still need unmatched left-table rows. Putting o.status = 'completed' in the WHERE clause would remove the NULL side of the left join.

5. Date bucket with boundary rules

Use this for daily active users, weekly revenue, monthly retention, or "last 7 days" questions.

SELECT
  DATE_TRUNC('day', event_time) AS event_day,
  COUNT(DISTINCT user_id) AS active_users
FROM events
WHERE event_time >= TIMESTAMP '2026-06-01'
  AND event_time < TIMESTAMP '2026-07-01'
GROUP BY DATE_TRUNC('day', event_time)
ORDER BY event_day;

Speed check: use a half-open interval: greater than or equal to the start, strictly less than the next period. It avoids off-by-one bugs with timestamps.

The 12-drill practice set

Run these drills with a timer. Do not use a solution until the timer ends. After each drill, write down the pattern and the mistake you almost made.

  1. One row per customer: total completed orders and revenue.
  2. One row per product: units sold, revenue, and first purchase date.
  3. Top three products by revenue in each category.
  4. Customers who signed up but never placed a completed order.
  5. Most recent subscription status per user.
  6. Daily active users for the previous full calendar month.
  7. Users whose second purchase happened within seven days of the first purchase.
  8. Monthly revenue and month-over-month percent change.
  9. Orders with more than one refund record, without double-counting order revenue.
  10. Products with a conversion rate below the category average.
  11. Accounts with activity in March but no activity in April.
  12. Sessions where checkout happened after add-to-cart but before purchase.

For a five-question speed round, randomly choose five of these and give yourself 30 minutes. For a three-question round, choose one grouped metric, one window function, and one missing-entity problem.

How to review after the timer

Speed improves when review is specific. Do not simply mark the answer right or wrong. Classify the failure.

  • Pattern failure: You did not recognize whether the problem was aggregation, latest row, top-N, anti-join, or date bucketing.
  • Grain failure: The query returned one row per event when the prompt asked for one row per user.
  • Join failure: A one-to-many join inflated the metric.
  • Filter failure: A WHERE clause changed a left join into an inner join or dropped NULLs accidentally.
  • Tie failure: The query worked on clean data but was nondeterministic when rows had equal timestamps or scores.
  • Communication failure: The SQL was close, but you did not explain assumptions or edge cases clearly.

Fix only one category at a time. If your problem is grain, do not spend the next practice block memorizing date functions. Practice naming the output row before writing SQL.

What to say when you get stuck

Silence makes a timed round feel worse. A concise recovery sentence keeps the interview moving:

  • "I want to confirm the output grain before I join these tables."
  • "This join may duplicate orders, so I am going to aggregate order_items first."
  • "If ties should be included, I would use DENSE_RANK. If exactly three rows are required, I would use ROW_NUMBER."
  • "I am using a half-open date range so timestamps later in the final day are not dropped."
  • "I have the core query. If we had more time, I would test it against duplicate keys and missing rows."

These sentences are not filler. They show that you know where SQL answers commonly break.

A weekly training plan

Use this for one week before a short SQL screen.

  • Day 1: Drill grouped metrics and anti-joins. Focus on grain and left join filters.
  • Day 2: Drill latest-row and top-N problems. Focus on tie rules.
  • Day 3: Drill date buckets and month-over-month metrics. Focus on timestamp boundaries.
  • Day 4: Run two 30-minute rounds with three questions each. Review mistakes by category.
  • Day 5: Run one 30-minute round with five questions. Do not over-polish early answers.
  • Day 6: Redo only the questions you missed. Explain each answer out loud.
  • Day 7: Light review. Memorize the opening routine, not a pile of solutions.

FAQ

Should I use CTEs in a timed SQL interview?

Yes, when they make the logic easier to read. A CTE is especially useful when you need to pre-aggregate, rank rows, or separate a metric calculation from a final filter. Do not use five CTEs when one grouped query is enough.

Should I optimize for the shortest query?

No. Optimize for a query you can explain and debug. In interviews, a slightly longer query with clear steps is usually better than a dense one-liner that hides the grain.

How many SQL problems should I practice before an interview?

Practice enough that the common patterns feel automatic. For many candidates, 30 targeted timed problems are more useful than 150 random untimed problems. The key is reviewing the failure category after every timed set.

What if I cannot finish all questions?

Finish the core answer first, then explain what you would test next. A correct simple query plus a clear edge-case discussion is better than an unfinished advanced query.

Final takeaway

Timed SQL interviews are won before the SQL is typed. If you can name the grain, pick the base table, recognize the pattern, and test one or two edge cases, you will move faster without guessing. Practice with a clock, review the type of mistake, and train the routine until every prompt starts the same way: output, grain, base table, filters, pattern.

Interview Prep

Begin Your SQL, Python, and R Journey

Master 230 interview-style coding questions and build the data skills needed for analyst, scientist, and engineering roles.

Related Articles

All Articles