SQL Practice Questions and Answers

·Updated Apr 4, 2026·
sqldatabasequery-languagesql practicesql exercisessql tutorial
·

Level: intermediate · ~22 min read · Intent: informational

Audience: backend developers, data analysts, data engineers, technical teams, students, junior developers, career switchers

Prerequisites

  • basic familiarity with databases
  • basic understanding of tables, rows, and columns

Key takeaways

  • The best way to improve in SQL is to practice solving real query problems, not just memorize syntax. Strong SQL skills come from understanding how to filter, join, group, sort, and reason about data shape.
  • Good SQL practice questions should test both correctness and thinking. The strongest learners explain what the query needs to return, identify the right tables and relationships, and then choose the SQL pattern that fits.

FAQ

What is the best way to practice SQL?
The best way to practice SQL is to solve real query problems repeatedly, explain what each query should return, and review why the answer works instead of only memorizing syntax.
Should SQL practice include JOINs and GROUP BY?
Yes. Good SQL practice should include filtering, sorting, joins, aggregates, GROUP BY, HAVING, subqueries, and NULL handling because these appear constantly in real SQL work.
Are SQL practice questions useful for interviews?
Yes. SQL practice questions are one of the best ways to prepare for interviews because they improve both query-writing speed and your ability to explain your reasoning clearly.
How do I know if my SQL answer is correct?
A SQL answer is more likely to be correct when you define the expected output clearly, check row counts, think about duplicates and NULL values, and make sure the query matches the real business question.
0

SQL gets easier when you stop thinking about it as a list of commands and start thinking about it as a way to answer questions about data.

That is why practice matters so much.

You do not really learn SQL by only reading definitions of:

  • SELECT
  • WHERE
  • JOIN
  • GROUP BY
  • ORDER BY

You learn SQL by using those tools to answer real questions like:

  • which customers placed the most orders?
  • which employees earn above the department average?
  • which products have never been sold?
  • how many users signed up last month?
  • what was the previous order amount for each customer?
  • which emails appear more than once?

That is what SQL practice questions are really for.

They train you to:

  • understand the data model
  • identify the correct output
  • choose the right SQL pattern
  • and avoid common mistakes with duplicates, NULL values, grouping, and joins

This guide gives you practical SQL practice questions and answers, with explanations designed to help you understand the reasoning instead of only copying the query.

Why SQL practice matters more than memorization

A lot of people try to learn SQL by memorizing syntax first.

That helps a little, but it is not enough.

The real challenge in SQL is usually not remembering that GROUP BY exists. The real challenge is knowing:

  • when you need GROUP BY
  • when you need HAVING
  • when a LEFT JOIN is better than an INNER JOIN
  • when duplicates are caused by joins
  • when NULL changes the result
  • and what one row in the final output should actually represent

That is why practice questions are so powerful.

They train your thinking, not only your memory.

The more real SQL questions you solve, the more naturally you start recognizing patterns.

The most important rule

Before working through practice questions, remember this:

Always define what one row in the output should represent before you write the query.

That is one of the most important SQL habits you can build.

For example:

  • one row per customer
  • one row per order
  • one row per department
  • one row per product
  • one row per month

If you do not define that clearly, it becomes very easy to:

  • join the wrong tables
  • group at the wrong level
  • count duplicates
  • or return the wrong result shape

So a strong SQL workflow always starts by asking:

  • what should each output row mean?

That question will help you solve almost every practice problem more accurately.

Simple example schema used in these questions

To keep the questions practical, imagine you are working with tables like these.

customers

  • customer_id
  • customer_name
  • email
  • country
  • created_at

orders

  • order_id
  • customer_id
  • order_date
  • total_amount
  • status

products

  • product_id
  • product_name
  • category
  • price

order_items

  • order_item_id
  • order_id
  • product_id
  • quantity
  • unit_price

employees

  • employee_id
  • employee_name
  • department
  • salary
  • manager_id

These are common tables in SQL practice and interviews because they make it easy to test filtering, joining, aggregation, and relationships.

SQL Practice Question 1: Return all customers

Question:
Write a query to return all rows and columns from the customers table.

Answer

SELECT *
FROM customers;

Explanation

This is the most basic SQL query pattern.

It says:

  • select all columns
  • from the customers table

This is useful for previewing data, but in real applications you often want to select only the columns you actually need.

SQL Practice Question 2: Return specific columns

Question:
Write a query to return only customer_name and email from the customers table.

Answer

SELECT customer_name, email
FROM customers;

Explanation

This is better than SELECT * when you only need a few fields.

It keeps the query:

  • clearer
  • more focused
  • and often more efficient

This is a good habit to build early.

SQL Practice Question 3: Filter rows with WHERE

Question:
Write a query to return customers from South Africa only.

Answer

SELECT
    customer_id,
    customer_name,
    email,
    country
FROM customers
WHERE country = 'South Africa';

Explanation

WHERE filters rows before they are returned.

This query keeps only customers where country is exactly 'South Africa'.

This is one of the most common SQL patterns.

SQL Practice Question 4: Sort results

Question:
Write a query to list all products from most expensive to least expensive.

Answer

SELECT
    product_id,
    product_name,
    category,
    price
FROM products
ORDER BY price DESC;

Explanation

ORDER BY price DESC sorts rows by price from highest to lowest.

This is useful for:

  • top-priced products
  • rankings
  • and admin views

If you wanted cheapest first, you would use ASC instead.

SQL Practice Question 5: Return the first 5 rows

Question:
Write a query to return the first 5 products.

Answer

SELECT
    product_id,
    product_name,
    price
FROM products
LIMIT 5;

Explanation

LIMIT 5 means:

  • return only 5 rows

This is often used for:

  • previews
  • top-N queries
  • debugging
  • and pagination

In real applications, LIMIT is usually best used with ORDER BY.

SQL Practice Question 6: Count all customers

Question:
Write a query to count how many customers exist.

Answer

SELECT COUNT(*) AS customer_count
FROM customers;

Explanation

COUNT(*) counts rows.

This query returns one row with one value:

  • the total number of customer records

This is one of the most common beginner SQL exercises.

SQL Practice Question 7: Count customers by country

Question:
Write a query to count how many customers exist in each country.

Answer

SELECT
    country,
    COUNT(*) AS customer_count
FROM customers
GROUP BY country;

Explanation

This query groups rows by country and counts how many rows exist in each group.

This is a very important SQL pattern:

  • GROUP BY creates groups
  • aggregate functions like COUNT summarize them

SQL Practice Question 8: Filter grouped results with HAVING

Question:
Write a query to return only countries that have more than 10 customers.

Answer

SELECT
    country,
    COUNT(*) AS customer_count
FROM customers
GROUP BY country
HAVING COUNT(*) > 10;

Explanation

HAVING filters grouped results after aggregation.

This is different from WHERE, which filters rows before grouping.

This is one of the most common SQL comparison concepts:

  • WHERE for raw rows
  • HAVING for grouped results

SQL Practice Question 9: INNER JOIN two tables

Question:
Write a query to return order IDs and customer names for all matching orders and customers.

Answer

SELECT
    o.order_id,
    o.order_date,
    c.customer_name
FROM orders o
INNER JOIN customers c
    ON o.customer_id = c.customer_id;

Explanation

This query joins:

  • orders
  • with customers

using the shared customer_id field.

INNER JOIN returns only rows that match in both tables.

This is one of the most important SQL skills.

SQL Practice Question 10: LEFT JOIN to keep unmatched rows

Question:
Write a query to return all customers and any matching orders they may have.

Answer

SELECT
    c.customer_id,
    c.customer_name,
    o.order_id,
    o.order_date,
    o.total_amount
FROM customers c
LEFT JOIN orders o
    ON c.customer_id = o.customer_id;

Explanation

LEFT JOIN keeps all rows from the left table:

  • customers

If a customer has no order, the order columns become NULL.

This is very useful when you want:

  • all customers
  • including customers with no orders yet

SQL Practice Question 11: Find customers with no orders

Question:
Write a query to return customers who have never placed an order.

Answer

SELECT
    c.customer_id,
    c.customer_name,
    c.email
FROM customers c
LEFT JOIN orders o
    ON c.customer_id = o.customer_id
WHERE o.order_id IS NULL;

Explanation

This is a classic SQL pattern.

It works because:

  • LEFT JOIN keeps all customers
  • customers with no matching orders get NULL in order columns
  • WHERE o.order_id IS NULL keeps only those unmatched rows

This is a very common interview question too.

SQL Practice Question 12: Find duplicate emails

Question:
Write a query to return email addresses that appear more than once in the customers table.

Answer

SELECT
    email,
    COUNT(*) AS duplicate_count
FROM customers
GROUP BY email
HAVING COUNT(*) > 1;

Explanation

This query:

  • groups rows by email
  • counts how many times each email appears
  • returns only those groups with more than one row

This is the standard SQL pattern for finding duplicates.

SQL Practice Question 13: Find the highest salary

Question:
Write a query to return the highest salary in the employees table.

Answer

SELECT MAX(salary) AS highest_salary
FROM employees;

Explanation

MAX(salary) returns the largest value in the salary column.

This is one of the most basic aggregate queries.

SQL Practice Question 14: Find the second highest salary

Question:
Write a query to return the second highest salary in the employees table.

Answer

SELECT MAX(salary) AS second_highest_salary
FROM employees
WHERE salary < (
    SELECT MAX(salary)
    FROM employees
);

Explanation

The inner query finds the highest salary.

The outer query then finds the maximum salary below that value.

This is a classic SQL interview and practice problem because it tests:

  • subqueries
  • aggregate functions
  • logical problem-solving

SQL Practice Question 15: Average salary by department

Question:
Write a query to return the average salary for each department.

Answer

SELECT
    department,
    AVG(salary) AS avg_salary
FROM employees
GROUP BY department;

Explanation

This groups employees by department and calculates the average salary in each group.

This is a common reporting pattern.

SQL Practice Question 16: Employees above department average

Question:
Write a query to return employees whose salary is above the average salary of their own department.

Answer

SELECT
    e.employee_id,
    e.employee_name,
    e.department,
    e.salary
FROM employees e
WHERE e.salary > (
    SELECT AVG(e2.salary)
    FROM employees e2
    WHERE e2.department = e.department
);

Explanation

This is a correlated subquery.

For each employee row, the subquery calculates:

  • the average salary in that employee’s department

Then the outer query keeps only employees whose salary is above that average.

This is a very strong SQL practice question because it introduces more realistic logic.

SQL Practice Question 17: Total sales per product

Question:
Write a query to return total quantity sold per product.

Answer

SELECT
    p.product_id,
    p.product_name,
    SUM(oi.quantity) AS total_quantity_sold
FROM products p
INNER JOIN order_items oi
    ON p.product_id = oi.product_id
GROUP BY
    p.product_id,
    p.product_name;

Explanation

This query joins:

  • products
  • to order_items

Then it groups by product and sums the quantity.

This is a common example of:

  • joins
  • aggregation
  • and one-to-many relationships

SQL Practice Question 18: Revenue per product

Question:
Write a query to return total revenue per product using quantity * unit_price.

Answer

SELECT
    p.product_id,
    p.product_name,
    SUM(oi.quantity * oi.unit_price) AS total_revenue
FROM products p
INNER JOIN order_items oi
    ON p.product_id = oi.product_id
GROUP BY
    p.product_id,
    p.product_name;

Explanation

This calculates revenue at the order item level, then sums it per product.

This is a very practical SQL exercise because it combines:

  • arithmetic expressions
  • grouping
  • and joins

SQL Practice Question 19: Top 5 customers by revenue

Question:
Write a query to return the top 5 customers by total order revenue.

Answer

SELECT
    c.customer_id,
    c.customer_name,
    SUM(o.total_amount) AS total_revenue
FROM customers c
INNER JOIN orders o
    ON c.customer_id = o.customer_id
GROUP BY
    c.customer_id,
    c.customer_name
ORDER BY total_revenue DESC
LIMIT 5;

Explanation

This is a classic top-N query.

It:

  • joins customers to orders
  • sums total order value per customer
  • sorts by revenue descending
  • returns only the top 5

This is a very realistic SQL reporting task.

SQL Practice Question 20: Latest order per customer using a window function

Question:
Write a query to return the latest order for each customer.

Answer

WITH ranked_orders AS (
    SELECT
        o.*,
        ROW_NUMBER() OVER (
            PARTITION BY customer_id
            ORDER BY order_date DESC, order_id DESC
        ) AS rn
    FROM orders o
)
SELECT
    order_id,
    customer_id,
    order_date,
    total_amount,
    status
FROM ranked_orders
WHERE rn = 1;

Explanation

This uses ROW_NUMBER() to rank each customer’s orders from newest to oldest.

Then:

  • WHERE rn = 1 keeps only the latest order for each customer.

This is one of the most useful real-world SQL patterns.

SQL Practice Question 21: Find previous order amount with LAG

Question:
Write a query to return each customer’s orders along with the previous order amount.

Answer

SELECT
    customer_id,
    order_id,
    order_date,
    total_amount,
    LAG(total_amount) OVER (
        PARTITION BY customer_id
        ORDER BY order_date, order_id
    ) AS previous_order_amount
FROM orders;

Explanation

LAG looks backward within each customer’s order history.

This is useful for:

  • comparing purchases over time
  • change detection
  • and customer behavior analysis

This is a strong intermediate SQL practice question.

SQL Practice Question 22: Use CASE for categorization

Question:
Write a query to classify products into price bands:

  • Expensive if price >= 1000
  • Mid Range if price >= 200 and < 1000
  • Budget otherwise

Answer

SELECT
    product_id,
    product_name,
    price,
    CASE
        WHEN price >= 1000 THEN 'Expensive'
        WHEN price >= 200 THEN 'Mid Range'
        ELSE 'Budget'
    END AS price_band
FROM products;

Explanation

CASE lets you build conditional labels in SQL.

This is useful in:

  • reporting
  • classification
  • business rules
  • and dashboard logic

SQL Practice Question 23: Handle NULL values with COALESCE

Question:
Write a query to return customer names and phone numbers, showing 'No phone number' when the phone number is NULL.

Answer

SELECT
    customer_name,
    COALESCE(phone_number, 'No phone number') AS phone_display
FROM customers;

Explanation

COALESCE returns the first non-NULL value.

This is one of the most useful SQL NULL-handling tools.

It is commonly used for:

  • display values
  • fallback logic
  • and replacing NULL where a clearer result is needed

SQL Practice Question 24: Count customers with zero orders

Question:
Write a query to return all customers and how many orders each customer has, including customers with zero orders.

Answer

SELECT
    c.customer_id,
    c.customer_name,
    COUNT(o.order_id) AS order_count
FROM customers c
LEFT JOIN orders o
    ON c.customer_id = o.customer_id
GROUP BY
    c.customer_id,
    c.customer_name;

Explanation

This is a very important SQL pattern.

Because it uses:

  • LEFT JOIN
  • and COUNT(o.order_id)

customers with no orders will correctly get:

  • 0

If you used COUNT(*) here, the result would be misleading for unmatched rows.

SQL Practice Question 25: Find products never ordered

Question:
Write a query to return products that have never appeared in order_items.

Answer

SELECT
    p.product_id,
    p.product_name
FROM products p
LEFT JOIN order_items oi
    ON p.product_id = oi.product_id
WHERE oi.order_item_id IS NULL;

Explanation

This uses the same unmatched-row pattern as “customers with no orders.”

It is one of the most useful SQL anti-join style patterns:

  • keep all products
  • then return only those with no match

SQL Practice Question 26: Monthly order totals

Question:
Write a query to return total revenue per month.

Answer

SELECT
    DATE_TRUNC('month', order_date) AS order_month,
    SUM(total_amount) AS total_revenue
FROM orders
GROUP BY DATE_TRUNC('month', order_date)
ORDER BY order_month;

Explanation

This groups orders by month and sums total revenue.

The exact month-truncation function varies by database, but the reporting pattern is very common:

  • group by time period
  • calculate totals
  • sort chronologically

SQL Practice Question 27: Customers who ordered more than 3 times

Question:
Write a query to return customers who placed more than 3 orders.

Answer

SELECT
    customer_id,
    COUNT(*) AS order_count
FROM orders
GROUP BY customer_id
HAVING COUNT(*) > 3;

Explanation

This is a classic grouped filter problem.

Use:

  • GROUP BY to form customer groups
  • COUNT(*) to count orders
  • HAVING to keep only customers above the threshold

This is one of the most common SQL practice patterns.

SQL Practice Question 28: Rank employees by salary within department

Question:
Write a query to rank employees by salary inside each department, highest salary first.

Answer

SELECT
    employee_id,
    employee_name,
    department,
    salary,
    RANK() OVER (
        PARTITION BY department
        ORDER BY salary DESC
    ) AS salary_rank
FROM employees;

Explanation

This uses a window function to create a rank inside each department.

This is useful for:

  • leaderboards
  • internal rankings
  • top performers
  • and per-group comparisons

It is also good SQL interview practice.

SQL Practice Question 29: Remove duplicates while keeping one row

Question:
Suppose a table contains duplicate emails. Write a query pattern to identify duplicates and keep only one row per email.

Answer

WITH ranked_customers AS (
    SELECT
        *,
        ROW_NUMBER() OVER (
            PARTITION BY email
            ORDER BY customer_id
        ) AS rn
    FROM customers
)
SELECT *
FROM ranked_customers
WHERE rn = 1;

Explanation

This query does not delete duplicates yet. It identifies the first row per email using ROW_NUMBER().

This is safer because you can inspect the result first.

This is a very strong SQL practice pattern for:

  • deduplication
  • cleanup
  • and data quality work

SQL Practice Question 30: Explain why a query result is duplicated after a join

Question:
You join customers to orders and see the same customer name repeated multiple times. Why?

Answer

Because one customer can have many orders.

A join returns one result row per match. So if one customer matches three orders, that customer appears three times.

Explanation

This is one of the most important SQL concepts:

  • joins follow relationship cardinality

If the relationship is one-to-many, row multiplication is expected.

This is not a bug unless the final output was supposed to be one row per customer. If that was the goal, then you usually need:

  • grouping
  • aggregation
  • window functions
  • or a different query structure

This is an excellent SQL reasoning question because it tests understanding, not just syntax.

How to get more value from SQL practice questions

SQL practice becomes much more useful when you do more than copy the final answer.

A stronger practice workflow looks like this:

1. Define the result in plain language

What should one row represent?

2. Identify the table or tables

Which tables hold the needed data?

3. Think about relationships

Do you need a join? Is the relationship one-to-many?

4. Decide whether you need filtering, grouping, sorting, or ranking

This helps choose the right SQL pattern.

5. Write the query

Try it before checking the answer.

6. Explain why it works

This is where real learning happens.

That method improves SQL much faster than passive reading.

Common SQL mistakes these practice questions help fix

Working through real SQL questions helps expose recurring mistakes like:

  • using WHERE when HAVING is required
  • using INNER JOIN when LEFT JOIN is needed
  • forgetting that one-to-many joins multiply rows
  • using COUNT(*) when COUNT(column_name) is more appropriate
  • mishandling NULL values
  • grouping at the wrong level
  • forgetting stable ordering when using LIMIT
  • and solving row-by-row problems without considering window functions

These are exactly the kinds of mistakes practice is supposed to fix.

How to keep improving after these questions

Once you are comfortable with the questions in this guide, the next best areas to practice are:

  • more join problems
  • duplicate cleanup
  • grouped reporting
  • window functions
  • date filtering
  • subqueries
  • CTEs
  • performance reasoning
  • and execution plan basics

That is the natural progression from beginner-to-intermediate SQL.

FAQ

What is the best way to practice SQL?

The best way to practice SQL is to solve real query problems repeatedly, explain what each query should return, and review why the answer works instead of only memorizing syntax.

Should SQL practice include JOINs and GROUP BY?

Yes. Good SQL practice should include filtering, sorting, joins, aggregates, GROUP BY, HAVING, subqueries, and NULL handling because these appear constantly in real SQL work.

Are SQL practice questions useful for interviews?

Yes. SQL practice questions are one of the best ways to prepare for interviews because they improve both query-writing speed and your ability to explain your reasoning clearly.

How do I know if my SQL answer is correct?

A SQL answer is more likely to be correct when you define the expected output clearly, check row counts, think about duplicates and NULL values, and make sure the query matches the real business question.

Final thoughts

SQL practice questions are valuable because they teach you to think in data, not just commands.

The real goal is not to memorize 100 query templates. The real goal is to become comfortable answering questions like:

  • what should the result look like?
  • which tables hold the data?
  • what does one row represent?
  • how do joins affect row count?
  • when do I group?
  • when do I rank?
  • how do NULL values affect the answer?

Once you start thinking that way, SQL becomes much easier to learn and much easier to use well.

That is why practice matters so much.

Not because it helps you remember syntax alone, but because it helps you recognize the patterns that appear in real SQL work again and again.

SQL guides

Explore the connected SQL guides on fundamentals, joins, analytics, performance, interviews, and practical workflows.

Pillar guide

SQL Complete Guide for Beginners and Developers

A complete SQL guide for beginners and developers covering databases, tables, SELECT, WHERE, JOINs, GROUP BY, CASE, subqueries, CTEs, inserts, updates, deletes, indexes, and practical query patterns.

View all SQL guides →

Related posts