SQLExcelHTML & CSSTouch typingBlogChoose a course
Lurndo › Blog › SQL
  1. Short answer
  2. What does an SQL interview test look like?
  3. Basic SQL interview questions
  4. SQL aggregate questions: WHERE vs HAVING and COUNT
  5. SQL join interview questions
  6. ROW_NUMBER vs RANK vs DENSE_RANK: what's the difference?
  7. LIMIT, TOP or FETCH FIRST: which SQL dialect will the test use?
  8. How do you prepare for an SQL interview?
  9. Frequently asked questions

SQL interview questions for beginners, with answers you can run

Most SQL interview tests ask the same handful of questions and set the same traps. Here they are, with the answer, the query and the result on real data, and two you can solve right on this page.

C

Christophe, founder of Lurndo
November 4, 2026 · 13 min read

SQL interview questions for beginners nearly always cover the same ground: filtering rows with WHERE, counting and grouping with GROUP BY and HAVING, combining tables with JOIN, and sometimes ranking with RANK. What sets you apart is the traps: = NULL that never matches, a LEFT JOIN you forgot, or a SUM that comes out too high after a join.

Exercise: right in your browser, on real data

Practise this: the lesson on LEFT JOIN, free

Sources: 6 sources you can check

A calm job interview table made of cut paper, with two empty chairs facing each other, an open laptop showing a table of rows, a cup of coffee and an empty speech bubble, on pale violet paper.

What does an SQL interview test look like?

An SQL interview test is usually short and practical: you get a few tables, such as customers and orders, and a handful of questions to answer with a query. Sometimes it's an online editor, sometimes a whiteboard, sometimes you talk a query through with your future team. The questions rarely touch obscure functions. They check whether you get the basics right every time, even when the data doesn't play along.

Employers ask because data work keeps growing. The US Bureau of Labor Statistics projects employment of data scientists to grow 35% from 2025 to 2035, with a median pay of $120,230 in May 2025 (BLS). And SQL isn't niche among people who build software either: 61.3% of professional developers use it (Stack Overflow).

Caveat: the BLS page doesn't mention SQL. Read it as demand for data work in the US, not as a count of jobs that ask for SQL.

How much SQL do you need for a data analyst job?

Less than you'd fear, but it has to be solid. For a data analyst, finance or marketing role, the core usually does: SELECT and WHERE, GROUP BY with COUNT and SUM, HAVING, INNER and LEFT JOIN, and often one window function such as RANK. If you can apply that core without slips, on data with empty fields and duplicate rows, you're better placed than someone who vaguely knows a hundred functions.

Every example below runs on the data of Bean & Co., the Bristol coffee roastery from the first module of our course. It has four tables: customers, products, orders and order_lines. Every result you read here comes from those tables, and you'll solve two of the questions yourself. Never written a query? Start with what SQL is and how a query works.

Order line: one product in one order, with its quantity and unit price. An order has one or more.

Basic SQL interview questions

The first questions look easy, and that's the point: the interviewer wants to see that you know exactly what a query does, including the edge cases beginners trip over. These three come up in one form or another again and again.

In what order does SQL run a query?

Not in the order you write it. You type SELECT first, but the database starts at FROM: which table? Then WHERE keeps the right rows, GROUP BY makes groups, HAVING filters those groups, and only then does SELECT pick the columns. ORDER BY and LIMIT come last. Once you know that order, you'll see at once why COUNT isn't allowed in WHERE.

FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT

Logical order: how the database reads a query. How it computes it internally is up to the database, but the result is the same.

What's the difference between = NULL and IS NULL?

NULL means there's no value, so nothing compares equal to it: even NULL = NULL isn't true, it's unknown. That's why WHERE email = NULL never returns a row, and you don't get an error either. Three of Bean & Co.'s customers have no email address. The first query below finds none of them, the second finds all three: Amira El Idrissi, Noah Jenkins and Dara Smyth.

-- 0 rows, and no error
SELECT name FROM customers WHERE email = NULL;

-- 3 rows
SELECT name FROM customers WHERE email IS NULL;

NULL: no value at all, not zero and not empty text. You test for it with IS NULL or IS NOT NULL, as in the lesson on IS NULL.

The same trap hides in NOT IN: one NULL in the list and the query returns no rows. See EXISTS and NOT IN.

Why does this query return too many rows?

A classic: the interviewer asks for the customers from Bristol or Cardiff who joined in 2024 or later, and hands you this query. It runs, returns three names and looks fine at first glance. So what's wrong with it?

SELECT name, city, member_since
FROM customers
WHERE city = 'Bristol' OR city = 'Cardiff'
AND member_since >= '2024-01-01';

AND binds tighter than OR, the way multiplication goes before addition. So the database reads: customers from Bristol, or customers from Cardiff who joined in 2024. That lets Lottie Parker slip through, a member since 2023, simply for living in Bristol. Put brackets around city = 'Bristol' OR city = 'Cardiff' and only Fern Mayes and Lucas Morgan are left, the two who really match.

SQL aggregate questions: WHERE vs HAVING and COUNT

Once counting starts, the test moves from rows to groups. That's where many answers go wrong, because the query runs fine but counts something other than you think. Two differences are worth being able to explain on the spot, ideally with an example ready.

What's the difference between WHERE and HAVING?

WHERE filters rows before grouping; HAVING filters groups after. That's the short answer, and the interviewer will usually ask for an example next. This query counts the customers with an email address in each city and only shows the cities with at least two of them.

SELECT city, COUNT(*) AS customers
FROM customers
WHERE email IS NOT NULL
GROUP BY city
HAVING COUNT(*) >= 2;
WHEREHAVING
Filtersrowsgroups
Runsbefore GROUP BYafter GROUP BY
COUNT or SUM insideerrorallowed
Drops herethe three customers without an emailcities with one customer, like London

The result: Bristol with 3 and Cardiff with 2. Without the WHERE, London would be there too, with two customers, but Amira El Idrissi has no email address. Put COUNT(*) >= 2 in WHERE and you get an error, because the groups don't exist yet at that point. Practise the difference in the lesson on HAVING.

COUNT(*) vs COUNT(column): what's the difference?

COUNT(*) counts rows, COUNT(email) only counts the rows where email isn't NULL, and COUNT(DISTINCT city) counts the different values. On one table that gives three different answers, and the interviewer wants to hear that you know which one you need.

SELECT COUNT(*), COUNT(email), COUNT(DISTINCT city)
FROM customers;
COUNT(*)COUNT(email)COUNT(DISTINCT city)
1298

Twelve customers, nine with an email address, from eight cities. Answer "how many customers have an email?" with COUNT(*) and you're three out. The difference really bites with a LEFT JOIN, further down: there, COUNT(*) happily counts a row full of NULLs.

SQL join interview questions

Joins are at the heart of almost every SQL test, because real data rarely sits in one table. Expect questions on which kind of join to pick, how to find what's missing, and why a total stops adding up after a join.

What's the difference between INNER JOIN and LEFT JOIN?

An INNER JOIN, or just JOIN, keeps only the rows that have a match in both tables. A LEFT JOIN keeps every row from the left table, match or not, and fills the right-hand columns with NULL where there's none. Join Bean & Co.'s 12 products to their 25 order lines and JOIN gives 25 rows, LEFT JOIN 26: the Travel Mug was never ordered and only shows up with a LEFT JOIN.

Left table: the table before LEFT JOIN. Swap the tables and you're asking a different question. More in the lesson on JOIN.

How do you find customers who never placed an order?

This may be the best-known SQL interview question of all, and the answer is a pattern: a LEFT JOIN to the orders, then keep only the rows where nothing was found on the right. A plain JOIN can never answer it, because it drops the customers without orders before WHERE gets a look.

SELECT c.name
FROM customers c
LEFT JOIN orders o ON o.customer_id = c.id
WHERE o.id IS NULL;

At Bean & Co. this query returns no rows, because every customer has ordered at least once. That's a correct answer too, and it's worth saying so out loud in an interview: an empty result isn't a mistake when the query is right. The same pattern on the products does find something. Try it yourself.

Try it: which product has never been ordered?

Rosa wants to know which products have never been ordered. Show their name. Every product sold is a row in order_lines.

If the interviewer then asks for the number of order lines per product, zeros included, count COUNT(ol.id), not COUNT(*). With COUNT(*) the Travel Mug gets 1, because its row of empty order columns counts too. The lesson on LEFT JOIN builds up both patterns step by step.

Filter on a right-hand column in WHERE after a LEFT JOIN, such as o.status = 'delivered', and the unmatched rows drop out again: their NULL never matches. Put that condition in ON instead.

Why is my SUM too high after a JOIN?

Because one row on the left matches several rows on the right, and the join repeats it. Rosa wants the stock and the units sold for each category. This query looks sensible, runs without an error and gives a number for every category. Only the stock is wrong everywhere.

SELECT p.category, SUM(p.stock) AS stock, SUM(ol.quantity) AS sold
FROM products p
JOIN order_lines ol ON ol.product_id = p.id
GROUP BY p.category;

For capsules it reports 530 in stock, while there are 120 Lungo Capsules and 85 Ristretto Capsules: 205 in all. For beans it's worse, 343 instead of 90. Look at the rows before they're summed and you'll see exactly why.

namestockquantity
Lungo Capsules1203
Lungo Capsules1206
Lungo Capsules1205

Lungo Capsules appears in three order lines, so SUM(p.stock) counts that 120 three times. The units sold are right, because they live in the order lines themselves. The fix: total the order lines per product first, so each product has a single row, and only join after that.

SELECT p.category, SUM(p.stock) AS stock, SUM(s.sold) AS sold
FROM products p
LEFT JOIN (
SELECT product_id, SUM(quantity) AS sold
FROM order_lines
GROUP BY product_id
) s ON s.product_id = p.id
GROUP BY p.category;

Now capsules show 205, with 20 sold. Thanks to the LEFT JOIN, the stock of the Travel Mug, which never sold, counts too. In an interview, the best thing you can do here is ask a question back first: what level does each number live at, per product or per order line?

ROW_NUMBER vs RANK vs DENSE_RANK: what's the difference?

All three number rows in an order you choose, and they only differ on a tie. You need them for leaderboards, a top 3 per category or the best customer in each city, and the question behind them is always the same: what happens to equal values?

What happens with a tie?

ROW_NUMBER always gives a different number, even for equal values. RANK gives ties the same number and then skips places. DENSE_RANK also gives ties the same number, but carries on counting without a gap. Rank Bean & Co.'s customers by their number of orders and you'll see the difference straight away.

SELECT c.name, COUNT(o.id) AS orders,
ROW_NUMBER() OVER (ORDER BY COUNT(o.id) DESC) AS row_num,
RANK() OVER (ORDER BY COUNT(o.id) DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY COUNT(o.id) DESC) AS dense_rnk
FROM customers c
JOIN orders o ON o.customer_id = c.id
GROUP BY c.id, c.name;

Window function: a function with OVER (...) that calculates across a set of rows without collapsing them. It runs after GROUP BY.

nameordersrow_numrnkdense_rnk
Lottie Parker3111
Jonah Clarke2222
Shane de Barra2322
the nine other customers14 to 1243

Jonah and Shane both have two orders. ROW_NUMBER still has to pick who comes second, and that choice isn't fixed. RANK gives them both 2 and then jumps to 4, because three customers come before. DENSE_RANK moves on to 3. Ask for a top 2 and rnk <= 2 returns three customers, row_num <= 2 only two. Practise it in the lesson on RANK and DENSE_RANK.

How do you find the second-highest salary?

The second-highest salary is a fixture of SQL interview questions. Bean & Co. has no salaries, so take the price: the Hand Grinder costs £39, the Pour-over Set £27.50. There are three common answers, and they're not all equally good:

  1. ORDER BY price DESC LIMIT 1 OFFSET 1: short, but wrong if two products share the top price. Then you get the highest price again.
  2. MAX with a subquery: the highest price below the highest price. That works in every dialect.
  3. DENSE_RANK() OVER (ORDER BY price DESC) and keep place 2. The same query gets you the third or the tenth.

Try it: which product is the second most expensive?

Which product has the second-highest price? Show its name and price.

LIMIT, TOP or FETCH FIRST: which SQL dialect will the test use?

Just ask. The core of SQL is the same everywhere, but each system limits the number of rows its own way. SQLite, MySQL and PostgreSQL use LIMIT. PostgreSQL itself calls that its own syntax, also used by MySQL, and points out that the standard has had OFFSET ... FETCH FIRST for the same job since SQL:2008 (PostgreSQL). SQL Server writes TOP.

SystemThe three most expensive products
SQLite, MySQL, PostgreSQLSELECT name, price FROM products ORDER BY price DESC LIMIT 3
SQL ServerSELECT TOP (3) name, price FROM products ORDER BY price DESC
SQL standard, PostgreSQLSELECT name, price FROM products ORDER BY price DESC FETCH FIRST 3 ROWS ONLY

Microsoft itself advises always using TOP together with ORDER BY: without it, you get the first rows in an undefined order (Microsoft). LIMIT is no different. If someone asks for "the three most expensive", they want a sort, not any three, and it's worth saying so in the interview.

If you practise on SQLite, as you do here, check the version of your own tool. Window functions have been in SQLite since version 3.25.0 from 2018 (SQLite), and RIGHT and FULL OUTER JOIN only since 3.39.0 from 2022 (SQLite). Lurndo runs a recent version in your browser, so everything in this article works there.

Which system you'll meet at work depends on the company. Among professional developers, PostgreSQL leads with 58.2%, ahead of MySQL, SQLite and SQL Server at 30.9% (Stack Overflow). Know the core well, and you'll adapt to any of those dialects quickly.

Source: a survey of developers, mostly reached through Stack Overflow itself. Not a cross-section of all workers, let alone all data analysts.

Databases used by professional developers in 2025
  1. PostgreSQL58.2%
  2. MySQL39.6%
  3. SQLite36.9%
  4. SQL Server30.9%

Source: Stack Overflow Developer Survey 2025, professional developers

How do you prepare for an SQL interview?

By writing queries, not by reading them. Memorising a list of answers doesn't help much once the tables look different from the ones in your example. What does help is five habits you apply to every exercise, until they come without thinking:

  1. Practise on real tables. Write every query yourself and look at the result, not just the code.
  2. Hunt for edge cases. What happens with NULL, with a tie, with a row that has no match?
  3. Count your rows. How many do you expect? If there are more after a JOIN, something is repeating.
  4. Think out loud. Say what each line does. That way the interviewer hears how you think, even if you forget a detail.
  5. Ask about the dialect. LIMIT or TOP? One question, and you won't lose time on a syntax error.

Learn SQL for a job interview shows which modules come up most in tests, and SQL practice exercises has exercises by topic, with hints and an explanation for every answer. Every query you write really runs and is checked on its result, not on how it's spelled. The first three modules are free.

Frequently asked questions

What SQL questions are asked in interviews for beginners?

Mostly filtering rows with WHERE, counting and grouping with GROUP BY and HAVING, and combining tables with JOIN, often a LEFT JOIN to find what's missing. Sometimes a window function such as RANK comes up. The traps are in NULL, ties and joins that repeat rows, so practise those on purpose.

How do I prepare for an SQL interview?

Write queries yourself on real tables and check every result. For each question, look at the edge cases, such as empty values, ties and rows without a match. Practise explaining out loud what your query does, and ask beforehand which database they use, so you know whether to write LIMIT or TOP.

How much SQL does a data analyst need?

For an entry-level role the core usually does, as long as it's solid. Think SELECT and WHERE, GROUP BY with COUNT and SUM, HAVING, INNER and LEFT JOIN, and a window function like ROW_NUMBER or RANK. Applying those without slips on messy data counts for more than vaguely knowing many functions.

What is the difference between WHERE and HAVING?

WHERE filters rows before grouping; HAVING filters groups after. That's why an aggregate like COUNT or SUM is allowed in HAVING but not in WHERE: when WHERE runs, the groups don't exist yet. You can use both in one query, WHERE for the rows and HAVING for the groups.

What's the difference between a primary key and a foreign key?

A primary key makes each row unique, like id in the customers table. A foreign key points to the primary key of another table, like customer_id in orders. That's how the database knows which customer an order belongs to, and it's what you join on. More in the lesson on keys.

Do I need to memorise SQL syntax for an interview?

The basics, yes. You should write SELECT, WHERE, GROUP BY and JOIN without looking anything up. The exact spelling of a date function is often fine to look up or ask about during the interview, so just say so. If you know what you're looking for, you'll find it fast. Sound reasoning counts for more than a comma.

Practise this in the course

Every lesson explains first and then lets you practise yourself, with a real database in your browser.

  • LEFT JOINFifth day · Forget no one with LEFT JOIN
  • HAVINGFourth day · Filtering groups with HAVING
  • IS NULLSecond day · Missing values with IS NULL
  • Ranking with RANK and DENSE_RANKEighth day · Same time
Start SQL for free

Sources

  1. US Bureau of Labor Statistics, Data Scientists, Occupational Outlook Handbook
  2. Stack Overflow, Stack Overflow Developer Survey 2025, Technology (2025)
  3. PostgreSQL, SELECT, LIMIT Clause and Compatibility
  4. Microsoft Learn, TOP (Transact-SQL)
  5. SQLite, Window Functions
  6. SQLite, SQLite Release 3.39.0 (2022-06-25)
C

Christophe, founder of Lurndo

Christophe builds Lurndo from Belgium, with short, playful exercises for SQL, Excel, HTML & CSS and touch typing that show straight away what your answer does. On this blog, Christophe answers the questions people run into while learning, with sources you can check yourself.

Read next

  • What is SQL? How to ask a database a questionYou don't need to be a programmer to ask a database a question. Here's what SQL is, where you already use it, and your first query, right in this page.SQL · November 4, 2026 · 6 min read
  • How to calculate an average in Excel: blanks, zeros, conditions and weighted averagesIt's one function, yet averages go wrong all the time. See how AVERAGE works, what it skips, and how to average without zeros, with a condition or with weights, on real spreadsheets.Excel · November 5, 2026 · 11 min read

SQL

  • Topics
  • All lessons
  • Cheat sheet
  • Sandbox

Excel

  • Topics
  • All lessons
  • Cheat sheet
  • Shortcuts

HTML & CSS

  • Topics
  • All lessons
  • Cheat sheet

Touch typing

  • Topics
  • All lessons
  • Cheat sheet
  • Typing test

Lurndo

  • Dashboard
  • Leaderboard
  • Premium
  • Account
  • Blog
  • FAQ
  • Contact & support
  • Privacy
Nederlands