Hack4Hack

SQL practice questions with answers

Practise SQL and MySQL questions at your own pace: joins, GROUP BY, NULLs, subqueries, window functions and indexes. Pick an answer to see whether you are right and why. Nothing is timed or ranked here; for that, play the Daily Quiz at 4 PM IST.

  1. Which clause sorts the result?

    easy

    1. GROUP BY
    2. ORDER BY
    3. SORT BY
    4. HAVING

    Answer: B. ORDER BY

    Explanation: ORDER BY col ASC (the default) or DESC. GROUP BY groups rows for aggregates; it does not guarantee any order.

  2. What does this return?

    easy

    -- orders(id, customer, amount):
    -- (1, Asha, 500) (2, Ravi, 300) (3, Asha, 200) (4, Meera, NULL)
    SELECT COUNT(DISTINCT customer) FROM orders;
    1. 4
    2. 3
    3. 2
    4. NULL

    Answer: B. 3

    Explanation: Asha appears twice, so there are 3 distinct customers: Asha, Ravi and Meera.

  3. Which keyword limits the number of rows returned in MySQL?

    easy

    1. TOP
    2. LIMIT
    3. FIRST
    4. ROWNUM

    Answer: B. LIMIT

    Explanation: MySQL and PostgreSQL use LIMIT n (with OFFSET for paging). SQL Server uses TOP; Oracle uses FETCH FIRST or ROWNUM.

  4. Which statement changes existing rows?

    easy

    1. INSERT
    2. UPDATE
    3. ALTER
    4. SELECT

    Answer: B. UPDATE

    Explanation: UPDATE changes data in rows; ALTER changes the table structure. Always check the WHERE clause before running an UPDATE.

  5. What does this return?

    medium

    -- orders(id, customer, amount):
    -- (1, Asha, 500) (2, Ravi, 300) (3, Asha, 200) (4, Meera, NULL)
    SELECT customer, SUM(amount) AS total
    FROM orders
    GROUP BY customer
    ORDER BY total DESC
    LIMIT 1;
    1. Asha 700
    2. Asha 500
    3. Ravi 300
    4. Meera NULL

    Answer: A. Asha 700

    Explanation: Asha: 500 + 200 = 700, Ravi 300, Meera NULL (SUM of only NULLs is NULL). In MySQL NULLs sort last in DESC order, so Asha is first.

  6. What does this return?

    medium

    -- orders(id, customer, amount):
    -- (1, Asha, 500) (2, Ravi, 300) (3, Asha, 200) (4, Meera, NULL)
    SELECT COUNT(*) FROM orders WHERE amount > 250 OR amount IS NULL;
    1. 2
    2. 3
    3. 4
    4. 1

    Answer: B. 3

    Explanation: 500 and 300 are above 250, and Meera's NULL matches IS NULL: 3 rows. A plain amount > 250 alone would skip the NULL row.

  7. Which query lists customers who have never placed an order?

    medium

    1. SELECT c.name FROM customers c LEFT JOIN orders o ON o.customer_id = c.id WHERE o.id IS NULL
    2. SELECT c.name FROM customers c JOIN orders o ON o.customer_id = c.id
    3. SELECT name FROM customers WHERE id = NULL
    4. SELECT name FROM orders WHERE amount = 0

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

    Explanation: An anti-join: the LEFT JOIN keeps every customer, and customers with no matching order have NULLs on the orders side. NOT EXISTS works too.

  8. What is a correlated subquery?

    medium

    1. A subquery in the FROM clause
    2. A subquery that refers to columns of the outer query, so it is evaluated per outer row
    3. A subquery that returns one value
    4. A JOIN written in reverse

    Answer: B. A subquery that refers to columns of the outer query, so it is evaluated per outer row

    Explanation: For example, WHERE salary > (SELECT AVG(salary) FROM employees e2 WHERE e2.dept = e1.dept). It is often rewritten as a join or a window function.

  9. What does LAG(amount) OVER (ORDER BY id) return for the first row?

    hard

    1. 0
    2. NULL
    3. The first row's amount
    4. An error

    Answer: B. NULL

    Explanation: LAG reads the previous row; the first row has none, so NULL (or the default you pass as the third argument). LEAD reads the next row.

  10. Which query finds each customer's largest order, ties included?

    hard

    1. SELECT * FROM (SELECT *, DENSE_RANK() OVER (PARTITION BY customer ORDER BY amount DESC) r FROM orders) t WHERE r = 1
    2. SELECT customer, MAX(id) FROM orders GROUP BY customer
    3. SELECT * FROM orders ORDER BY amount DESC LIMIT 1
    4. SELECT DISTINCT customer, amount FROM orders

    Answer: A. SELECT * FROM (SELECT *, DENSE_RANK() OVER (PARTITION BY customer ORDER BY amount DESC) r FROM orders) t WHERE r = 1

    Explanation: Partitioning ranks orders within each customer. MAX(id) finds the latest order, not the largest.

  11. EXPLAIN shows "type: ALL" for a query on a 10-million-row table. What does it mean?

    hard

    1. All indexes are used
    2. A full table scan: every row is read, usually because no usable index exists for the filter
    3. The query returns all rows
    4. The query is cached

    Answer: B. A full table scan: every row is read, usually because no usable index exists for the filter

    Explanation: Add an index on the filtered column, and avoid wrapping that column in a function in the WHERE clause.

  12. Which make an index unusable for a WHERE filter on the column? (Select all that apply)

    hard

    1. WHERE YEAR(created_at) = 2026
    2. WHERE name LIKE '%kumar'
    3. WHERE created_at >= '2026-01-01'
    4. WHERE CAST(phone AS UNSIGNED) = 98765

    Answer: A. WHERE YEAR(created_at) = 2026; B. WHERE name LIKE '%kumar'; D. WHERE CAST(phone AS UNSIGNED) = 98765

    Explanation: Functions on the column and leading wildcards hide the sorted order the index relies on. A plain range comparison can use it.

From past Daily Quizzes

  1. Which clause filters groups after GROUP BY?

    SQL · easy

    1. WHERE
    2. HAVING
    3. ORDER BY
    4. LIMIT

    Answer: B. HAVING

    Explanation: WHERE filters rows before grouping; HAVING filters the groups, so it can use aggregates like COUNT(*) > 5.

  2. What does the running total return for the third row?

    SQL · hard

    SELECT d, amt, SUM(amt) OVER (ORDER BY d) AS running
    FROM sales;
    -- rows (d, amt): ('2026-01-01', 10), ('2026-01-02', 20), ('2026-01-02', 5), ('2026-01-03', 7)
    1. 30
    2. 35
    3. 5
    4. 42

    Answer: B. 35

    Explanation: With ORDER BY and no frame clause the default frame is RANGE … CURRENT ROW, which includes all peers with the same d. Both 2026-01-02 rows show 10 + 20 + 5 = 35. Use ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW for a strict row-by-row total.

  3. Which JOIN returns every row from the left table, with NULLs where there is no match on the right?

    SQL · easy

    1. INNER JOIN
    2. LEFT JOIN
    3. CROSS JOIN
    4. SELF JOIN

    Answer: B. LEFT JOIN

    Explanation: LEFT (OUTER) JOIN keeps all left rows. INNER JOIN keeps only rows that match on both sides.

  4. What does this return?

    SQL · easy

    SELECT name FROM employees WHERE name LIKE 'M%';
    -- names: Asha, Ravi, Meera, Kabir, Neha
    1. Meera
    2. Meera, Neha
    3. Asha, Meera
    4. No rows

    Answer: A. Meera

    Explanation: 'M%' matches names starting with M. % is any run of characters and _ is exactly one.

  5. What does this return?

    SQL · hard

    SELECT * FROM a WHERE id NOT IN (SELECT a_id FROM b);
    -- a.id: 1, 2, 3
    -- b.a_id: 1, NULL
    1. 2, 3
    2. No rows
    3. 1
    4. 1, 2, 3

    Answer: B. No rows

    Explanation: id NOT IN (1, NULL) means id <> 1 AND id <> NULL. Comparing with NULL is unknown, so no row qualifies. NOT EXISTS does not have this trap.

  6. What does this recursive CTE return?

    SQL · hard

    WITH RECURSIVE n(x) AS (
      SELECT 1
      UNION ALL
      SELECT x * 2 FROM n WHERE x < 20
    )
    SELECT SUM(x) FROM n;
    1. 31
    2. 63
    3. 30
    4. 62

    Answer: B. 63

    Explanation: Rows: 1, 2, 4, 8, 16, then 32 (16 < 20 still passes, producing 32; 32 stops the recursion). 1+2+4+8+16+32 = 63.

  7. What does this return?

    SQL · medium

    -- Table employees(id, name, dept, salary):
    -- (1, Asha,  Eng,   90)
    -- (2, Ravi,  Eng,   70)
    -- (3, Meera, Sales, 60)
    -- (4, Kabir, Sales, 60)
    -- (5, Neha,  HR,    NULL)
    SELECT dept, COUNT(*) AS n
    FROM employees
    GROUP BY dept
    HAVING COUNT(*) > 1
    ORDER BY dept;
    1. Eng 2, Sales 2
    2. Eng 2, HR 1, Sales 2
    3. Sales 2
    4. Eng 2

    Answer: A. Eng 2, Sales 2

    Explanation: Eng and Sales have 2 employees each; HR has 1 and is filtered out by HAVING.

  8. Table A has 3 rows and table B has 4 rows. How many rows does SELECT * FROM A CROSS JOIN B return?

    SQL · medium

    1. 7
    2. 12
    3. 4
    4. 3

    Answer: B. 12

    Explanation: A cross join pairs every row of A with every row of B: 3 × 4 = 12 (a Cartesian product).

  9. Which statements are true about a VIEW? (Select all that apply)

    SQL · medium

    1. It is a stored query
    2. By default it does not store a copy of the data
    3. It always makes queries faster
    4. It can hide columns from users

    Answer: A. It is a stored query; B. By default it does not store a copy of the data; D. It can hide columns from users

    Explanation: A view is a named SELECT that runs when queried, so it is not automatically faster (materialized views, which store results, are a different feature). Views are often used to expose only some columns.

Play the Daily Quiz at 4 PM IST