Skip to main content
    Interview Questions

    Master SQL Interviews: 50+ Database Questions for Career Success 2026

    True database experts think beyond syntax to understand query execution plans, indexing strategies, and system-level performance implications. Based on data professional hiring across industries, I've learned that exceptional SQL developers know how databases think, can explain query performance ...

    January 4, 2026
    35 min read
    20 views
    Craqly Team
    sql interview 2026
    database interview questions
    query optimization interview
    sql performance interview
    database design interview
    advanced sql interview
    interview
    interview questions

    Domain Overview

    SQL is the language of data. Whether you're a data analyst, backend developer, or DBA, SQL skills are fundamental. In 2026, interviewers expect you to not just write queries, but understand execution plans, indexing strategies, and how to optimize for millions of rows.

    What makes SQL interviews tricky is that syntax is easy to learn, but understanding query performance requires knowing how databases work internally—B-trees, query planners, join algorithms, and transaction isolation levels.

    Key Skills Interviewers Look For

    • Query Writing: JOINs, subqueries, CTEs, window functions
    • Performance: Indexes, EXPLAIN plans, query optimization
    • Data Modeling: Normalization, schema design, relationships
    • Aggregations: GROUP BY, HAVING, aggregate functions
    • Transactions: ACID, isolation levels, deadlocks
    • Advanced SQL: Recursive queries, pivoting, JSON handling
    • Database-specific: PostgreSQL vs MySQL differences
    • Real-world: Handling NULLs, data quality, migrations

    Fundamental Questions (Q1-Q15)

    1. Explain the different types of JOINs with examples.

    Expert Answer:

    {`-- Setup: users (id, name) | orders (id, user_id, amount)
    
    -- INNER JOIN: Only matching rows from both tables
    SELECT u.name, o.amount
    FROM users u
    INNER JOIN orders o ON u.id = o.user_id;
    
    -- LEFT JOIN: All rows from left table, matching from right
    SELECT u.name, o.amount
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id;
    -- Users without orders will have NULL for amount
    
    -- RIGHT JOIN: All rows from right table, matching from left
    -- (Less common, can rewrite as LEFT JOIN with swapped tables)
    
    -- FULL OUTER JOIN: All rows from both tables
    SELECT u.name, o.amount
    FROM users u
    FULL OUTER JOIN orders o ON u.id = o.user_id;
    
    -- CROSS JOIN: Cartesian product (every combination)
    SELECT u.name, p.product_name
    FROM users u
    CROSS JOIN products p;`}

    Key insight: The JOIN type determines which rows appear when there's no match. INNER = only matches. LEFT = all from left. FULL = all from both.

    2. What is the difference between WHERE and HAVING?

    Expert Answer:

    WHERE: Filters rows BEFORE grouping

    HAVING: Filters groups AFTER aggregation

    {`-- Find categories with more than 10 active products
    -- WHERE filters individual rows first
    -- HAVING filters the aggregated groups
    
    SELECT category, COUNT(*) as product_count
    FROM products
    WHERE status = 'active'          -- Filter rows before grouping
    GROUP BY category
    HAVING COUNT(*) > 10;            -- Filter groups after aggregation
    
    -- You can't use aggregate functions in WHERE:
    -- WHERE COUNT(*) > 10  ❌ ERROR!`}

    Execution order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY

    3. How do indexes work? When should you add an index?

    Expert Answer:

    Indexes are data structures (typically B-trees) that allow the database to find rows without scanning the entire table.

    {`-- Without index: Full table scan O(n)
    -- With index: B-tree lookup O(log n)
    
    CREATE INDEX idx_users_email ON users(email);
    
    -- Composite index for queries that filter on multiple columns
    CREATE INDEX idx_orders_user_date ON orders(user_id, created_at);
    
    -- Important: Column order matters!
    -- This index helps: WHERE user_id = 1 AND created_at > '2024-01-01'
    -- This index helps: WHERE user_id = 1
    -- This index does NOT help: WHERE created_at > '2024-01-01' alone`}

    When to add indexes:

    • Columns in WHERE clauses
    • Columns in JOIN conditions
    • Columns in ORDER BY
    • Foreign keys

    When NOT to add:

    • Small tables (full scan is fast anyway)
    • Columns with low cardinality (few unique values)
    • Tables with heavy writes (indexes slow down inserts/updates)

    4. What's the difference between UNION and UNION ALL?

    Expert Answer:

    {`-- UNION: Combines results and removes duplicates
    SELECT name FROM customers
    UNION
    SELECT name FROM suppliers;
    -- If "Acme Corp" appears in both, only one row in result
    
    -- UNION ALL: Combines all results, keeps duplicates
    SELECT name FROM customers
    UNION ALL
    SELECT name FROM suppliers;
    -- If "Acme Corp" appears in both, two rows in result
    
    -- Performance: UNION ALL is faster (no deduplication step)
    -- Use UNION ALL when you know there are no duplicates or want them`}

    5. Explain NULL handling in SQL.

    Expert Answer:

    NULL represents unknown/missing data. It's NOT the same as empty string or zero.

    {`-- NULL comparisons are tricky
    SELECT * FROM users WHERE age = NULL;     -- Returns nothing!
    SELECT * FROM users WHERE age IS NULL;    -- Correct way
    
    -- NULL in expressions propagates
    SELECT 5 + NULL;  -- Returns NULL
    SELECT NULL = NULL;  -- Returns NULL (not TRUE!)
    
    -- COALESCE: Returns first non-NULL value
    SELECT COALESCE(nickname, first_name, 'Anonymous') as display_name
    FROM users;
    
    -- NULLIF: Returns NULL if values are equal
    SELECT NULLIF(discount, 0)  -- Avoid division by zero
    FROM orders;
    
    -- NULL in aggregations
    SELECT AVG(age) FROM users;  -- NULLs are ignored
    SELECT COUNT(*) FROM users;  -- Counts all rows
    SELECT COUNT(age) FROM users; -- Counts non-NULL ages only`}

    6. What is a subquery? When would you use it vs a JOIN?

    Expert Answer:

    {`-- Subquery in WHERE (correlated)
    SELECT * FROM orders o
    WHERE amount > (
      SELECT AVG(amount) FROM orders WHERE user_id = o.user_id
    );
    
    -- Subquery in FROM (derived table)
    SELECT dept_name, avg_salary
    FROM (
      SELECT department_id, AVG(salary) as avg_salary
      FROM employees
      GROUP BY department_id
    ) dept_avg
    JOIN departments d ON dept_avg.department_id = d.id;
    
    -- Same query with JOIN (often more efficient)
    SELECT u.name, COUNT(o.id) as order_count
    FROM users u
    LEFT JOIN orders o ON u.id = o.user_id
    GROUP BY u.id, u.name;`}

    Use subquery when:

    • You need a scalar value for comparison
    • EXISTS/NOT EXISTS checks
    • The logic is clearer with nesting

    Use JOIN when:

    • You need columns from both tables
    • Usually better performance (optimizer can handle better)

    7-15. More Fundamental Questions:

    • 7. What is database normalization? Explain 1NF, 2NF, 3NF.
    • 8. What are primary keys and foreign keys?
    • 9. Explain the difference between DELETE, TRUNCATE, and DROP.
    • 10. What is the difference between VARCHAR and CHAR?
    • 11. How do you remove duplicates from a table?
    • 12. What is the difference between IN and EXISTS?
    • 13. How do you find the Nth highest salary?
    • 14. What are constraints in SQL (UNIQUE, CHECK, DEFAULT)?
    • 15. Explain the difference between RANK, DENSE_RANK, and ROW_NUMBER.

    Intermediate Questions (Q16-Q35)

    16. Explain window functions with examples.

    Expert Answer:

    Window functions perform calculations across rows related to the current row, without collapsing them like GROUP BY.

    {`-- Syntax: function() OVER (PARTITION BY ... ORDER BY ...)
    
    -- Running total
    SELECT
      date,
      amount,
      SUM(amount) OVER (ORDER BY date) as running_total
    FROM sales;
    
    -- Rank within groups
    SELECT
      department,
      employee,
      salary,
      RANK() OVER (PARTITION BY department ORDER BY salary DESC) as dept_rank
    FROM employees;
    
    -- Moving average (last 3 rows)
    SELECT
      date,
      amount,
      AVG(amount) OVER (
        ORDER BY date
        ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
      ) as moving_avg
    FROM sales;
    
    -- Lag/Lead: Access previous/next row
    SELECT
      date,
      amount,
      LAG(amount, 1) OVER (ORDER BY date) as prev_amount,
      amount - LAG(amount, 1) OVER (ORDER BY date) as daily_change
    FROM sales;`}

    17. How do you read and interpret an EXPLAIN plan?

    Expert Answer:

    {`EXPLAIN ANALYZE
    SELECT * FROM orders
    WHERE user_id = 123 AND created_at > '2024-01-01';
    
    -- Sample output (PostgreSQL):
    -- Index Scan using idx_orders_user_date on orders
    --   Index Cond: (user_id = 123 AND created_at > '2024-01-01')
    --   Rows Removed by Filter: 0
    --   Planning Time: 0.5 ms
    --   Execution Time: 2.3 ms`}

    Key things to look for:

    • Seq Scan: Full table scan - often bad for large tables
    • Index Scan: Using index - usually good
    • Bitmap Scan: Combines multiple indexes
    • Nested Loop vs Hash Join: Different join strategies
    • Estimated rows vs actual rows: Large differences indicate stale statistics

    18. What is a CTE (Common Table Expression)? When do you use it?

    Expert Answer:

    {`-- CTE: Named temporary result set
    WITH high_value_customers AS (
      SELECT user_id, SUM(amount) as total_spent
      FROM orders
      GROUP BY user_id
      HAVING SUM(amount) > 1000
    )
    SELECT u.name, hvc.total_spent
    FROM users u
    JOIN high_value_customers hvc ON u.id = hvc.user_id;
    
    -- Recursive CTE: For hierarchical data
    WITH RECURSIVE subordinates AS (
      -- Base case
      SELECT id, name, manager_id, 1 as level
      FROM employees
      WHERE id = 1  -- CEO
    
      UNION ALL
    
      -- Recursive case
      SELECT e.id, e.name, e.manager_id, s.level + 1
      FROM employees e
      JOIN subordinates s ON e.manager_id = s.id
    )
    SELECT * FROM subordinates;`}

    Benefits: Readability, reusability within query, required for recursion

    19-35. More Intermediate Questions:

    • 19. Explain ACID properties with examples.
    • 20. What are transaction isolation levels?
    • 21. How do you handle deadlocks?
    • 22. What is the difference between clustered and non-clustered indexes?
    • 23. How do you optimize a slow query?
    • 24. Explain denormalization. When is it appropriate?
    • 25. What are views? What are materialized views?
    • 26. How do stored procedures differ from functions?
    • 27. Explain triggers and their use cases.
    • 28. How do you implement soft deletes?
    • 29. What is table partitioning? When would you use it?
    • 30. How do you handle time zones in SQL?
    • 31. What is the difference between OLTP and OLAP?
    • 32. How do you write a pivot query?
    • 33. Explain database locking (row-level, table-level).
    • 34. What is query caching? How does it work?
    • 35. How do you handle large data migrations?

    Advanced & Real-World Questions (Q36-Q50)

    36. Design a database schema for an e-commerce platform.

    Expert Answer:

    {`-- Core tables
    users (id, email, password_hash, created_at)
    products (id, name, description, price, inventory_count)
    categories (id, name, parent_id)  -- Hierarchical
    product_categories (product_id, category_id)  -- Many-to-many
    
    -- Orders
    orders (id, user_id, status, total, created_at)
    order_items (id, order_id, product_id, quantity, price_at_time)
    -- Note: price_at_time captures price when ordered (prices change)
    
    -- Addresses (users can have multiple)
    addresses (id, user_id, type, street, city, country, is_default)
    
    -- Reviews
    reviews (id, user_id, product_id, rating, comment, created_at)
    
    -- Key indexes
    CREATE INDEX idx_orders_user ON orders(user_id);
    CREATE INDEX idx_order_items_order ON order_items(order_id);
    CREATE INDEX idx_products_category ON product_categories(category_id);`}

    Design decisions:

    • Store price_at_time in order_items (prices change)
    • Soft deletes for products (orders reference them)
    • Consider read replicas for product catalog (high read)

    37-50. More Advanced Questions:

    • 37. How do you implement full-text search in SQL?
    • 38. Design a query to find users with overlapping date ranges.
    • 39. How do you handle JSON data in SQL databases?
    • 40. Explain replication strategies (master-slave, multi-master).
    • 41. How do you implement rate limiting in SQL?
    • 42. Design a schema for a social network (friends, posts, likes).
    • 43. How do you track changes/audit history in a database?
    • 44. Explain database sharding strategies.
    • 45. How do you handle concurrent updates to inventory?
    • 46. Design a query for calculating business metrics (MRR, churn).
    • 47. How do you migrate from one database to another?
    • 48. Explain connection pooling and its importance.
    • 49. How do you backup and restore large databases?
    • 50. Design a data warehouse schema (star schema vs snowflake).

    Ace Your SQL Interview

    Practice writing queries and explaining your approach with Craqly. Get real-time feedback on your SQL problem-solving.

    Common Mistakes Candidates Make

    ❌ What to Avoid:

    • • Using SELECT * in production queries
    • • Ignoring NULL behavior in comparisons
    • • Not considering index usage
    • • Writing correlated subqueries when JOINs work
    • • Not explaining your thought process

    ✓ What Works:

    • • Specify exact columns needed
    • • Handle NULLs explicitly
    • • Think about query performance
    • • Use EXPLAIN to verify your assumptions
    • • Talk through your approach
    Share this article
    C

    Written by

    Craqly Team

    Comments

    Leave a comment

    No comments yet. Be the first to share your thoughts!

    Ready to Transform Your Interview Skills?

    Join thousands of professionals who have improved their interview performance with AI-powered practice sessions.