SQL · Interview Prep · 2026 Edition

SQL Interview Questions and Answers (2026 Edition)

100+ SQL interview questions with answers, real queries, output explanations and interview tips — built for freshers, data analysts, and software engineers preparing for 2026 interviews.

SQL Interview Questions and Answers 2026 cover image

If you're preparing for a Data Analyst, SQL Developer, Backend Engineer, or Software Engineering interview in 2026, this guide is built to be the only SQL resource you need. It covers SQL from the absolute basics all the way to advanced topics like window functions, recursive CTEs, transaction isolation levels, and real interview scenarios asked at product-based and service-based companies — with 100+ questions, real queries, output explanations, and interview tips.

Ankit Verma

Written by Ankit Verma (AnkitIQCode)

Software engineer and technical content creator writing practical, interview-focused tutorials on SQL, Python, and Data Analytics. Every query in this guide has been tested for correctness and written the way interviewers actually expect — clear, efficient, and explainable.

SQLPythonData AnalyticsPower BI

1. What is SQL?

SQL (Structured Query Language) is the standard language used to communicate with relational database management systems (RDBMS) like MySQL, PostgreSQL, SQL Server, and Oracle. It lets you define database structures, insert and modify data, retrieve information using powerful queries, and control access — all using a declarative, English-like syntax.

In simple terms: SQL is how humans and applications "talk" to structured, table-based data. Every time you check your bank balance, browse an e-commerce catalog, or view analytics on a dashboard, SQL is very likely working behind the scenes.

📌 Note: SQL is declarative, not procedural — you describe what data you want, not how to fetch it step by step. The database engine decides the most efficient execution path.

2. Features of SQL

  • Declarative syntax — describe the result, not the retrieval algorithm.
  • Platform independence — core SQL works across MySQL, PostgreSQL, SQL Server, Oracle with minor dialect differences.
  • Data integrity — constraints like PRIMARY KEY, FOREIGN KEY, and CHECK enforce valid data.
  • Powerful querying — joins, subqueries, and window functions support complex analytics.
  • Transaction support — COMMIT, ROLLBACK, and SAVEPOINT ensure safe multi-step operations.
  • Security & access control — GRANT and REVOKE manage who can do what.
  • Scalability — modern RDBMSs handle everything from small apps to petabyte-scale warehouses.

3. SQL Commands: DDL, DML, DCL, TCL, DQL

SQL commands are grouped into five categories based on their purpose:

SQL Command Categories
CategoryFull FormPurposeExample Commands
DDLData Definition LanguageDefine/modify schema structureCREATE, ALTER, DROP, TRUNCATE
DMLData Manipulation LanguageManipulate actual dataINSERT, UPDATE, DELETE
DQLData Query LanguageRetrieve dataSELECT
DCLData Control LanguageManage permissionsGRANT, REVOKE
TCLTransaction Control LanguageManage transactionsCOMMIT, ROLLBACK, SAVEPOINT

DDL Example

SQL
CREATE TABLE Departments (
    dept_id INT PRIMARY KEY,
    dept_name VARCHAR(50) NOT NULL
);

ALTER TABLE Departments ADD COLUMN location VARCHAR(100);

DROP TABLE IF EXISTS OldDepartments;

DML Example

SQL
INSERT INTO Departments (dept_id, dept_name) VALUES (1, 'Engineering');

UPDATE Departments SET location = 'Bangalore' WHERE dept_id = 1;

DELETE FROM Departments WHERE dept_id = 99;

DCL Example

SQL
GRANT SELECT, INSERT ON Employees TO analyst_user;

REVOKE INSERT ON Employees FROM analyst_user;

TCL Example

SQL
BEGIN TRANSACTION;
UPDATE Employees SET salary = salary + 2000 WHERE dept_id = 1;
COMMIT;
💡 Interview Tip: Interviewers frequently ask "Is TRUNCATE DDL or DML?" — it's DDL. It auto-commits and cannot always be rolled back, unlike DELETE.

4. SQL Data Types

Common SQL Data Types
CategoryData TypesUse Case
NumericINT, BIGINT, DECIMAL, FLOATIDs, counts, prices, salaries
StringCHAR, VARCHAR, TEXTNames, descriptions, codes
Date/TimeDATE, TIME, DATETIME, TIMESTAMPOrder dates, timestamps
BooleanBOOLEAN / BITFlags like is_active
BinaryBLOB, VARBINARYImages, files

5. SQL Constraints

ConstraintPurpose
PRIMARY KEYUniquely identifies each row; no NULLs
FOREIGN KEYLinks to another table's primary key
UNIQUEEnsures all values in a column are distinct
NOT NULLDisallows NULL values
CHECKValidates values against a condition
DEFAULTAssigns a default value when none is provided
SQL
CREATE TABLE Employees (
    emp_id INT PRIMARY KEY,
    emp_name VARCHAR(50) NOT NULL,
    email VARCHAR(100) UNIQUE,
    salary DECIMAL(10,2) CHECK (salary > 0),
    dept_id INT,
    status VARCHAR(20) DEFAULT 'Active',
    FOREIGN KEY (dept_id) REFERENCES Departments(dept_id)
);

6. SQL Keys

Key TypeDescription
Primary KeyUniquely identifies a row; no NULLs; one per table
Foreign KeyReferences a primary key in another table
Candidate KeyAny column(s) eligible to be the primary key
Super KeyAny set of columns that uniquely identifies a row (may include extras)
Composite KeyPrimary key formed from two or more columns
Alternate KeyCandidate key not chosen as the primary key

7. SQL Operators

  • Arithmetic: +, -, *, /, %
  • Comparison: =, !=, <>, >, <, >=, <=
  • Logical: AND, OR, NOT, BETWEEN, IN, LIKE, IS NULL
  • Set: UNION, UNION ALL, INTERSECT, EXCEPT/MINUS

8. WHERE, ORDER BY, GROUP BY, HAVING

SQL
SELECT dept_id, COUNT(*) AS emp_count, AVG(salary) AS avg_salary
FROM Employees
WHERE status = 'Active'
GROUP BY dept_id
HAVING COUNT(*) > 3
ORDER BY avg_salary DESC;
📌 Execution order (not writing order): FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY. Interviewers love asking this — memorize it.

9. Aggregate Functions

Aggregate Function Comparison
FunctionPurposeHandles NULL?
COUNT(*)Counts all rowsIncludes NULL rows
COUNT(column)Counts non-null values in a columnIgnores NULL
SUM()Adds numeric valuesIgnores NULL
AVG()Calculates averageIgnores NULL
MIN() / MAX()Smallest/largest valueIgnores NULL

10. SQL JOINS (with Comparison Table)

Joins combine rows from two or more tables based on a related column. Here's a full comparison:

JOIN Types Comparison
JOIN TypeReturnsUnmatched Rows
INNER JOINOnly matching rows in both tablesExcluded
LEFT JOINAll left table rows + matchesRight side NULL
RIGHT JOINAll right table rows + matchesLeft side NULL
FULL OUTER JOINAll rows from both tablesNULL on non-matching side
SELF JOINTable joined to itselfDepends on join type used
CROSS JOINCartesian product (all combinations)N/A — no condition

INNER JOIN

SQL
SELECT e.emp_name, d.dept_name
FROM Employees e
INNER JOIN Departments d ON e.dept_id = d.dept_id;

LEFT JOIN

SQL
SELECT e.emp_name, d.dept_name
FROM Employees e
LEFT JOIN Departments d ON e.dept_id = d.dept_id;

RIGHT JOIN

SQL
SELECT e.emp_name, d.dept_name
FROM Employees e
RIGHT JOIN Departments d ON e.dept_id = d.dept_id;

FULL OUTER JOIN

SQL
SELECT e.emp_name, d.dept_name
FROM Employees e
FULL OUTER JOIN Departments d ON e.dept_id = d.dept_id;

SELF JOIN

SQL
SELECT e.emp_name AS employee, m.emp_name AS manager
FROM Employees e
LEFT JOIN Employees m ON e.manager_id = m.emp_id;

CROSS JOIN

SQL
SELECT p.product_name, s.size_name
FROM Products p
CROSS JOIN Sizes s;
⚠️ Common Mistake: Forgetting the ON condition in a JOIN accidentally turns it into a CROSS JOIN, producing a massive, incorrect result set. Always double-check your join conditions.

11. UNION vs UNION ALL

AspectUNIONUNION ALL
DuplicatesRemovedKept
PerformanceSlower (dedup overhead)Faster
Use CaseNeed distinct combined resultsDuplicates are fine/expected
SQL
SELECT emp_name FROM Employees
UNION ALL
SELECT cust_name FROM Customers;

12. Views

A view is a stored SELECT query that acts as a virtual table — useful for simplifying complex queries and restricting access to sensitive columns.

SQL
CREATE VIEW EmployeePublic AS
SELECT emp_id, emp_name, dept_id FROM Employees;

SELECT * FROM EmployeePublic;

13. Indexes

Indexes speed up data retrieval at the cost of extra storage and slightly slower writes.

SQL
CREATE INDEX idx_employee_email ON Employees(email);
💡 Best Practice: Index columns used frequently in WHERE, JOIN, and ORDER BY clauses — but avoid over-indexing write-heavy tables.

14. Stored Procedures

SQL
CREATE PROCEDURE GiveRaise (IN p_dept_id INT, IN p_amount DECIMAL(10,2))
BEGIN
    UPDATE Employees SET salary = salary + p_amount WHERE dept_id = p_dept_id;
END;

CALL GiveRaise(3, 5000);

15. Triggers

SQL
CREATE TRIGGER trg_salary_audit
AFTER UPDATE ON Employees
FOR EACH ROW
BEGIN
    INSERT INTO SalaryAudit(emp_id, old_salary, new_salary, changed_at)
    VALUES (OLD.emp_id, OLD.salary, NEW.salary, NOW());
END;

16. Common Table Expressions (CTE)

SQL
WITH RankedEmp AS (
    SELECT emp_name, dept_id, salary,
    ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rnk
    FROM Employees
)
SELECT * FROM RankedEmp WHERE rnk <= 3;

17. Window Functions

Window Function Comparison
FunctionBehavior on Ties
ROW_NUMBER()Unique number for every row, no gaps
RANK()Same rank for ties, skips next rank(s)
DENSE_RANK()Same rank for ties, no skipped ranks
LAG() / LEAD()Access previous/next row's value
SQL
SELECT emp_name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn,
RANK() OVER (ORDER BY salary DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
FROM Employees;

18. Subqueries & Correlated Subqueries

SQL
-- Simple Subquery
SELECT emp_name FROM Employees
WHERE salary > (SELECT AVG(salary) FROM Employees);

-- Correlated Subquery
SELECT e1.emp_name, e1.salary FROM Employees e1
WHERE e1.salary > (
    SELECT AVG(e2.salary) FROM Employees e2 WHERE e2.dept_id = e1.dept_id
);

19. Transactions & ACID Properties

PropertyMeaning
AtomicityAll operations succeed, or none do
ConsistencyData moves between valid states only
IsolationConcurrent transactions don't interfere
DurabilityCommitted changes survive crashes
SQL
BEGIN TRANSACTION;
UPDATE Accounts SET balance = balance - 500 WHERE acct_id = 1;
UPDATE Accounts SET balance = balance + 500 WHERE acct_id = 2;
COMMIT;

20. Normalization & Denormalization

Normal FormRule
1NFAtomic values, no repeating groups
2NF1NF + no partial dependency on composite key
3NF2NF + no transitive dependency
BCNFEvery determinant is a candidate key
Denormalization intentionally adds redundancy to reduce joins and speed up reads — common in reporting/OLAP systems.

21. 100+ SQL Interview Questions and Answers

Below are 100 hand-crafted SQL interview questions covering beginner to advanced levels, complete with answers, example scenarios, working SQL queries, output explanations, and interview tips. Questions are tagged Easy, Medium, or Hard so you can prioritize your prep.

Beginner-Level SQL Interview Questions

Q1. What is SQL and why is it used?

Easy

Answer: SQL (Structured Query Language) is a standard language used to create, read, update, and delete data stored in a relational database. It lets you define table structures, insert and modify records, and run complex queries to retrieve exactly the data you need.

Example Scenario: A company stores employee records in a relational database and uses SQL to fetch employees hired after 2023.

SQL
SELECT emp_name, hire_date FROM Employees WHERE hire_date > '2023-01-01';
Output Explanation
Returns the name and hire date of every employee hired after 1 Jan 2023.
💡 Interview Tip: Always mention that SQL works with relational (table-based) databases and is both a data definition and data manipulation language — interviewers like to hear the DDL/DML distinction early.

Q2. What are the main features of SQL?

Easy

Answer: SQL is declarative (you describe what you want, not how to get it), platform-independent, supports multiple data types, allows complex joins and aggregations, enforces data integrity through constraints, and integrates transaction control for safe multi-step operations.

Example Scenario: You can write the same SELECT query on MySQL, PostgreSQL, or SQL Server with only minor syntax differences.

SQL
SELECT COUNT(*) FROM Employees;
Output Explanation
Returns the total number of rows in the Employees table.
💡 Interview Tip: List 4–5 features confidently; interviewers often just want to check you understand SQL is declarative, not procedural.

Q3. What are the different types of SQL commands?

Easy

Answer: SQL commands are grouped into five categories: DDL (Data Definition Language) for schema, DML (Data Manipulation Language) for data, DCL (Data Control Language) for permissions, TCL (Transaction Control Language) for transactions, and DQL (Data Query Language) for SELECT-based retrieval.

Example Scenario: CREATE TABLE (DDL), INSERT INTO (DML), GRANT (DCL), COMMIT (TCL), and SELECT (DQL) are all SQL commands from different categories.

SQL
CREATE TABLE Departments (dept_id INT PRIMARY KEY, dept_name VARCHAR(50));
Output Explanation
Creates a new Departments table with two columns — a DDL operation that changes the schema, not the data.
💡 Interview Tip: Draw a quick mental table of the 5 categories with 2 example commands each before the interview — this question shows up almost every time.

Q4. What is the difference between DDL and DML?

Easy

Answer: DDL commands (CREATE, ALTER, DROP, TRUNCATE) define or modify the structure of database objects and auto-commit. DML commands (INSERT, UPDATE, DELETE) manipulate the actual data inside tables and can be rolled back within a transaction.

Example Scenario: ALTER TABLE changes a table's structure (DDL); UPDATE changes the values inside it (DML).

SQL
ALTER TABLE Employees ADD COLUMN email VARCHAR(100);
UPDATE Employees SET email = 'a@b.com' WHERE emp_id = 1;
Output Explanation
First statement adds a new column to the schema; second statement fills in a value for one row.
💡 Interview Tip: Remember: DDL = structure, auto-committed; DML = data, rollback-able. This distinction is a classic trick question.

Q5. What is the difference between CHAR and VARCHAR?

Easy

Answer: CHAR is a fixed-length string type that pads unused space with blanks, making it faster for consistently sized data. VARCHAR is variable-length and stores only the actual characters used plus a small length indicator, saving space for variable data.

Example Scenario: A 2-letter state code fits CHAR(2); a customer name of variable length fits VARCHAR(50) better.

SQL
CREATE TABLE Customers (state CHAR(2), full_name VARCHAR(50));
Output Explanation
Creates a table where 'state' always occupies 2 bytes, while 'full_name' occupies only as many bytes as the actual name.
💡 Interview Tip: Say CHAR is faster for fixed-size codes (like country codes), VARCHAR saves storage for variable text — this shows practical understanding.

Q6. What are SQL constraints? Name the common ones.

Easy

Answer: Constraints are rules enforced on table columns to maintain data accuracy and integrity. Common constraints include PRIMARY KEY, FOREIGN KEY, UNIQUE, NOT NULL, CHECK, and DEFAULT.

Example Scenario: A CHECK constraint can ensure an employee's salary is always positive.

SQL
CREATE TABLE Employees (emp_id INT PRIMARY KEY, salary DECIMAL(10,2) CHECK (salary > 0));
Output Explanation
Any attempt to insert a negative salary will be rejected by the database.
💡 Interview Tip: Interviewers love follow-ups like 'what happens if you violate a constraint?' — know that it throws an error and the statement is rejected.

Q7. What is a Primary Key?

Easy

Answer: A Primary Key uniquely identifies each row in a table. It cannot contain NULL values, must be unique, and a table can have only one primary key (which may span multiple columns as a composite key).

Example Scenario: emp_id uniquely identifies each row in the Employees table.

SQL
CREATE TABLE Employees (emp_id INT PRIMARY KEY, emp_name VARCHAR(50));
Output Explanation
Guarantees that no two rows can ever have the same emp_id, and emp_id can never be NULL.
💡 Interview Tip: Mention composite primary keys — many candidates forget a primary key can consist of more than one column.

Q8. What is a Foreign Key?

Easy

Answer: A Foreign Key is a column (or set of columns) in one table that references the Primary Key of another table, enforcing referential integrity between the two tables.

Example Scenario: The dept_id column in Employees references dept_id in Departments.

SQL
CREATE TABLE Employees (emp_id INT PRIMARY KEY, dept_id INT, FOREIGN KEY (dept_id) REFERENCES Departments(dept_id));
Output Explanation
Ensures every dept_id entered in Employees must already exist in Departments, preventing orphan records.
💡 Interview Tip: Explain ON DELETE CASCADE / ON DELETE SET NULL as advanced follow-up knowledge — it shows depth.

Q9. What is the difference between Primary Key and Unique Key?

Easy

Answer: A Primary Key does not allow NULLs and only one exists per table. A Unique Key allows one NULL value (in most databases) and a table can have multiple unique keys.

Example Scenario: email can be a Unique Key allowing NULL for one row, while emp_id remains the single Primary Key.

SQL
CREATE TABLE Employees (emp_id INT PRIMARY KEY, email VARCHAR(100) UNIQUE);
Output Explanation
emp_id must always be present and unique; email must be unique among non-null values but one row could leave it NULL.
💡 Interview Tip: A very common trap question — always mention the NULL-handling difference explicitly.

Q10. What are the different types of SQL operators?

Easy

Answer: SQL operators include Arithmetic (+, -, *, /, %), Comparison (=, !=, >, <, >=, <=), Logical (AND, OR, NOT, BETWEEN, IN, LIKE), and Set operators (UNION, INTERSECT, EXCEPT/MINUS).

Example Scenario: The BETWEEN operator filters salaries within a given range.

SQL
SELECT emp_name FROM Employees WHERE salary BETWEEN 40000 AND 80000;
Output Explanation
Returns employees whose salary lies inclusively between 40,000 and 80,000.
💡 Interview Tip: Group operators into these 4 categories mentally — it helps you answer follow-up questions faster.

Q11. What is the difference between WHERE and HAVING?

Easy

Answer: WHERE filters individual rows before any grouping happens and cannot use aggregate functions. HAVING filters groups after GROUP BY has been applied and can use aggregate functions like SUM() or COUNT().

Example Scenario: You want departments with more than 5 employees.

SQL
SELECT dept_id, COUNT(*) AS emp_count FROM Employees GROUP BY dept_id HAVING COUNT(*) > 5;
Output Explanation
Returns only those dept_id groups whose employee count exceeds 5 — this filtering happens after grouping.
💡 Interview Tip: One-liner to remember: 'WHERE filters rows, HAVING filters groups.' Interviewers ask this in almost every SQL round.

Q12. What does the ORDER BY clause do?

Easy

Answer: ORDER BY sorts the result set by one or more columns, in ascending (ASC, default) or descending (DESC) order.

Example Scenario: Sort employees by salary from highest to lowest.

SQL
SELECT emp_name, salary FROM Employees ORDER BY salary DESC;
Output Explanation
Returns all employees sorted with the highest-paid employee first.
💡 Interview Tip: Mention you can sort by multiple columns and even by column position number (ORDER BY 2) — a nice bonus fact.

Q13. What is the purpose of the GROUP BY clause?

Easy

Answer: GROUP BY groups rows sharing the same values in specified columns so aggregate functions (SUM, AVG, COUNT, etc.) can be applied to each group separately.

Example Scenario: Find the total salary paid per department.

SQL
SELECT dept_id, SUM(salary) AS total_salary FROM Employees GROUP BY dept_id;
Output Explanation
Returns one row per department showing the sum of salaries for employees in that department.
💡 Interview Tip: Remember every non-aggregated column in SELECT must appear in GROUP BY — this is a frequent syntax error.

Q14. What is the difference between DELETE, TRUNCATE, and DROP?

Medium

Answer: DELETE removes rows one at a time (can use WHERE, is logged, rollback-able), TRUNCATE removes all rows at once (faster, minimal logging, resets identity, cannot use WHERE), and DROP removes the entire table structure along with its data permanently.

Example Scenario: You want to clear all data but keep the table structure for reuse.

SQL
TRUNCATE TABLE Employees;
Output Explanation
Instantly empties the Employees table while keeping its schema intact.
💡 Interview Tip: Say TRUNCATE is DDL (auto-commit, cannot rollback in most databases) while DELETE is DML — a classic gotcha.

Q15. What is a NULL value in SQL?

Easy

Answer: NULL represents missing, unknown, or inapplicable data. It is not the same as zero or an empty string, and any arithmetic or comparison with NULL returns NULL (unknown) — you must use IS NULL / IS NOT NULL to test for it.

Example Scenario: An employee record without a recorded phone number stores NULL, not '0' or ''.

SQL
SELECT emp_name FROM Employees WHERE phone IS NULL;
Output Explanation
Returns employees whose phone number has not been entered.
💡 Interview Tip: Never say 'salary = NULL' in a WHERE clause — explain why it silently returns nothing, since NULL comparisons are always unknown.

Q16. What is the difference between IN and BETWEEN?

Easy

Answer: IN checks whether a value matches any value in a specified list. BETWEEN checks whether a value falls within an inclusive range of two values.

Example Scenario: Filter employees who work in dept_id 1, 3, or 5, versus employees with salary between 30000 and 60000.

SQL
SELECT * FROM Employees WHERE dept_id IN (1,3,5);
SELECT * FROM Employees WHERE salary BETWEEN 30000 AND 60000;
Output Explanation
First query returns rows matching any listed dept_id; second returns rows with salary in that inclusive range.
💡 Interview Tip: Mention BETWEEN is inclusive on both ends — a detail interviewers often probe.

Q17. What is the LIKE operator used for?

Easy

Answer: LIKE performs pattern matching in string columns using wildcards: % for zero or more characters and _ for exactly one character.

Example Scenario: Find all employees whose name starts with 'A'.

SQL
SELECT emp_name FROM Employees WHERE emp_name LIKE 'A%';
Output Explanation
Returns every employee whose name begins with the letter A.
💡 Interview Tip: Know that LIKE is case-insensitive in MySQL by default but case-sensitive in PostgreSQL — mention this to show cross-database awareness.

Q18. What is the difference between UNION and UNION ALL?

Medium

Answer: UNION combines results from two SELECT queries and removes duplicate rows, which involves extra processing. UNION ALL combines results without removing duplicates, making it faster.

Example Scenario: Combine current employees and former employees lists.

SQL
SELECT emp_name FROM Employees
UNION
SELECT emp_name FROM FormerEmployees;
Output Explanation
Returns a merged, de-duplicated list of employee names from both tables.
💡 Interview Tip: If duplicates genuinely don't matter, always recommend UNION ALL for performance — a strong optimization talking point.

Q19. What are Aggregate Functions in SQL? Name a few.

Easy

Answer: Aggregate functions perform a calculation on a set of rows and return a single summarized value. Common ones are COUNT(), SUM(), AVG(), MIN(), and MAX().

Example Scenario: Find the average salary across the company.

SQL
SELECT AVG(salary) AS avg_salary FROM Employees;
Output Explanation
Returns one single value representing the average salary of all employees.
💡 Interview Tip: Mention that COUNT(*) counts all rows including NULLs, while COUNT(column) ignores NULLs in that column — a favorite trick question.

Q20. What is the difference between COUNT(*), COUNT(1), and COUNT(column_name)?

Medium

Answer: COUNT(*) counts all rows regardless of NULLs. COUNT(1) behaves the same as COUNT(*) in modern optimizers (counts all rows). COUNT(column_name) counts only rows where that specific column is NOT NULL.

Example Scenario: Count all employees vs count employees who have a manager assigned.

SQL
SELECT COUNT(*) AS total_emp, COUNT(manager_id) AS with_manager FROM Employees;
Output Explanation
total_emp shows every row; with_manager shows only rows where manager_id is not NULL.
💡 Interview Tip: Say COUNT(*) and COUNT(1) usually have identical performance in modern engines — don't fall for the myth that COUNT(1) is faster.

Q21. What is a Composite Key?

Medium

Answer: A Composite Key is a primary key made up of two or more columns that together uniquely identify a row, used when no single column is unique enough on its own.

Example Scenario: In an Enrollments table, (student_id, course_id) together form a composite key.

SQL
CREATE TABLE Enrollments (student_id INT, course_id INT, PRIMARY KEY (student_id, course_id));
Output Explanation
Ensures a student cannot be enrolled in the exact same course twice, but can enroll in multiple different courses.
💡 Interview Tip: Give a real-world junction-table example like this one — it demonstrates practical schema design thinking.

Q22. What is a Candidate Key?

Medium

Answer: A Candidate Key is any column or combination of columns that could qualify as a unique identifier for a table. One candidate key is chosen as the Primary Key; the rest become Alternate Keys.

Example Scenario: In Employees, both emp_id and email could independently identify a row uniquely, making both candidate keys.

SQL
-- emp_id and email are both candidate keys;
-- emp_id is chosen as Primary Key
Output Explanation
Only emp_id enforces uniqueness as the primary key, while email may still be marked UNIQUE separately.
💡 Interview Tip: Explain the hierarchy: Super Key → Candidate Key → Primary Key — this chain impresses interviewers.

Q23. What is a Super Key?

Medium

Answer: A Super Key is any set of one or more columns that can uniquely identify a row; it may include extra, unnecessary attributes. Every Candidate Key is a Super Key, but not every Super Key is minimal enough to be a Candidate Key.

Example Scenario: (emp_id, emp_name) is a super key because it's unique, even though emp_name alone isn't needed.

SQL
-- Super Key example: (emp_id, emp_name, dept_id)
Output Explanation
Uniquely identifies rows but carries redundant columns beyond what's minimally required.
💡 Interview Tip: Keep this crisp: 'Super Key ⊇ Candidate Key ⊇ Primary Key' — a clean way to summarize key hierarchy.

Q24. What is the difference between a Clustered and Non-Clustered Index?

Medium

Answer: A Clustered Index determines the physical storage order of table data — a table can have only one. A Non-Clustered Index creates a separate structure with pointers back to the actual data rows — a table can have many.

Example Scenario: Primary key columns typically get a clustered index automatically in SQL Server.

SQL
CREATE CLUSTERED INDEX idx_emp_id ON Employees(emp_id);
CREATE NONCLUSTERED INDEX idx_emp_name ON Employees(emp_name);
Output Explanation
The clustered index physically sorts the table by emp_id; the non-clustered index speeds up lookups by emp_name without reordering data.
💡 Interview Tip: Analogy that works well in interviews: clustered index = phone book sorted by name; non-clustered index = book's alphabetical topic index at the back.

Q25. What is Normalization? Name its normal forms briefly.

Medium

Answer: Normalization is the process of organizing data to reduce redundancy and improve data integrity by dividing large tables into smaller related ones. Key normal forms: 1NF (atomic values, no repeating groups), 2NF (no partial dependency on composite keys), 3NF (no transitive dependency), and BCNF (every determinant is a candidate key).

Example Scenario: Splitting a single 'Orders' table containing customer address into separate Orders and Customers tables removes repeated address data.

SQL
-- Before: Orders(order_id, cust_name, cust_address, product)
-- After 3NF:
-- Customers(cust_id, cust_name, cust_address)
-- Orders(order_id, cust_id, product)
Output Explanation
Splitting into two related tables eliminates redundant customer address data stored across many orders.
💡 Interview Tip: Be ready to explain 1NF, 2NF, 3NF with one-line examples each — this is asked in nearly every data analyst interview.

SQL JOIN Interview Questions

Q26. What is an INNER JOIN?

Easy

Answer: INNER JOIN returns only the rows that have matching values in both joined tables based on the join condition.

Example Scenario: Get employee names along with their department names, only for employees who have an assigned department.

SQL
SELECT e.emp_name, d.dept_name FROM Employees e INNER JOIN Departments d ON e.dept_id = d.dept_id;
Output Explanation
Returns only employees who have a matching department; employees with a NULL or invalid dept_id are excluded.
💡 Interview Tip: Draw two overlapping circles mentally — INNER JOIN is the intersection only.

Q27. What is a LEFT JOIN (LEFT OUTER JOIN)?

Easy

Answer: LEFT JOIN returns all rows from the left table and the matched rows from the right table; unmatched right-side columns are filled with NULL.

Example Scenario: List all employees, including those not yet assigned to any department.

SQL
SELECT e.emp_name, d.dept_name FROM Employees e LEFT JOIN Departments d ON e.dept_id = d.dept_id;
Output Explanation
Every employee appears in the result; dept_name is NULL for employees without a matching department.
💡 Interview Tip: Classic follow-up: 'How do you find employees with NO department?' Add WHERE d.dept_id IS NULL after the LEFT JOIN.

Q28. What is a RIGHT JOIN (RIGHT OUTER JOIN)?

Easy

Answer: RIGHT JOIN returns all rows from the right table and the matched rows from the left table; unmatched left-side columns are filled with NULL.

Example Scenario: List all departments, including ones with no employees assigned yet.

SQL
SELECT e.emp_name, d.dept_name FROM Employees e RIGHT JOIN Departments d ON e.dept_id = d.dept_id;
Output Explanation
Every department appears; emp_name is NULL for departments that currently have zero employees.
💡 Interview Tip: Mention that RIGHT JOIN is just a LEFT JOIN with tables swapped — many teams avoid RIGHT JOIN for readability.

Q29. What is a FULL OUTER JOIN?

Medium

Answer: FULL OUTER JOIN returns all rows from both tables, matching where possible and filling NULLs where no match exists on either side.

Example Scenario: List every employee and every department, matched where possible, unmatched on either side otherwise.

SQL
SELECT e.emp_name, d.dept_name FROM Employees e FULL OUTER JOIN Departments d ON e.dept_id = d.dept_id;
Output Explanation
Shows matched employee-department pairs, plus employees without departments and departments without employees.
💡 Interview Tip: Note MySQL lacks native FULL OUTER JOIN — mention simulating it with LEFT JOIN UNION RIGHT JOIN.

Q30. What is a SELF JOIN?

Medium

Answer: A SELF JOIN joins a table to itself, typically to compare rows within the same table, such as finding employees and their managers stored in the same table.

Example Scenario: Find each employee along with their manager's name, where manager_id references emp_id in the same table.

SQL
SELECT e.emp_name AS employee, m.emp_name AS manager FROM Employees e LEFT JOIN Employees m ON e.manager_id = m.emp_id;
Output Explanation
Each row shows an employee's name paired with their manager's name from the same Employees table.
💡 Interview Tip: Always use table aliases for self joins — interviewers check if you know aliasing is mandatory here.

Q31. What is a CROSS JOIN?

Medium

Answer: CROSS JOIN returns the Cartesian product of two tables — every row from the first table paired with every row from the second, with no join condition.

Example Scenario: Generate every possible combination of Products and Sizes for a catalog.

SQL
SELECT p.product_name, s.size_name FROM Products p CROSS JOIN Sizes s;
Output Explanation
If Products has 5 rows and Sizes has 3 rows, the result contains 15 rows — every combination.
💡 Interview Tip: Warn that CROSS JOIN on large tables can explode row counts — always mention this performance risk.

Q32. How do you find employees who do NOT belong to any department?

Medium

Answer: Use a LEFT JOIN from Employees to Departments and filter for rows where the department key is NULL, meaning no match was found.

Example Scenario: Departments without a matching entry in Departments for some employees.

SQL
SELECT e.emp_name FROM Employees e LEFT JOIN Departments d ON e.dept_id = d.dept_id WHERE d.dept_id IS NULL;
Output Explanation
Returns only employees whose dept_id had no corresponding row in the Departments table.
💡 Interview Tip: This LEFT JOIN + IS NULL pattern is one of the most frequently asked practical SQL questions — memorize it.

Advanced SQL Interview Questions

Q33. What is a Subquery?

Medium

Answer: A Subquery (or inner query) is a query nested inside another SQL query, used to return data that the outer query then uses for filtering, comparison, or as a derived table.

Example Scenario: Find employees who earn more than the company's average salary.

SQL
SELECT emp_name, salary FROM Employees WHERE salary > (SELECT AVG(salary) FROM Employees);
Output Explanation
Returns employees whose individual salary exceeds the overall average salary computed by the inner query.
💡 Interview Tip: Distinguish scalar subqueries (single value), row subqueries, and table subqueries — interviewers may ask you to classify one.

Q34. What is a Correlated Subquery?

Hard

Answer: A Correlated Subquery references a column from the outer query, so it re-executes once for every row processed by the outer query, unlike a regular subquery that runs independently.

Example Scenario: Find employees earning more than the average salary of their own department.

SQL
SELECT e1.emp_name, e1.salary FROM Employees e1 WHERE e1.salary > (SELECT AVG(e2.salary) FROM Employees e2 WHERE e2.dept_id = e1.dept_id);
Output Explanation
For each employee, the inner query recalculates the department average and compares only within that same department.
💡 Interview Tip: Explain the performance trade-off: correlated subqueries can be slow on large tables — often rewritten using window functions.

Q35. What is the difference between a Subquery and a JOIN?

Medium

Answer: A JOIN combines columns from multiple tables into one result set in a single pass and is usually more efficient for retrieving combined data. A Subquery is often used for filtering or existence checks and can be less efficient, especially when correlated, though it can be more readable for certain logic.

Example Scenario: Get employees along with department names — better solved with a JOIN than a subquery.

SQL
-- JOIN approach
SELECT e.emp_name, d.dept_name FROM Employees e JOIN Departments d ON e.dept_id = d.dept_id;
Output Explanation
Returns combined employee and department data in a single efficient pass, rather than a row-by-row subquery lookup.
💡 Interview Tip: Say: 'I prefer JOINs for combining columns, subqueries for existence checks or scalar comparisons' — shows judgment, not just syntax knowledge.

Q36. What is a Common Table Expression (CTE)?

Medium

Answer: A CTE, defined with WITH, is a temporary named result set that exists only for the duration of a single query, improving readability and enabling recursive queries.

Example Scenario: Find the top 3 highest-paid employees per department using a CTE with ROW_NUMBER().

SQL
WITH RankedEmp AS (
  SELECT emp_name, dept_id, salary,
  ROW_NUMBER() OVER (PARTITION BY dept_id ORDER BY salary DESC) AS rnk
  FROM Employees
)
SELECT * FROM RankedEmp WHERE rnk <= 3;
Output Explanation
Returns up to 3 highest-paid employees within each department, ranked by salary in descending order.
💡 Interview Tip: Mention CTEs are not materialized/cached by default in most databases — they're re-evaluated each reference, unlike temp tables.

Q37. What is a Recursive CTE? Give an example.

Hard

Answer: A Recursive CTE references itself to process hierarchical or recursive data, such as organizational charts or category trees, by combining an anchor query with a recursive query joined back to the CTE.

Example Scenario: Find all employees under a given manager, including indirect reports, in an org hierarchy.

SQL
WITH RECURSIVE OrgChart AS (
  SELECT emp_id, emp_name, manager_id FROM Employees WHERE manager_id IS NULL
  UNION ALL
  SELECT e.emp_id, e.emp_name, e.manager_id FROM Employees e
  JOIN OrgChart o ON e.manager_id = o.emp_id
)
SELECT * FROM OrgChart;
Output Explanation
Starts from top-level managers (anchor) and recursively adds each level of subordinates until no more matches remain.
💡 Interview Tip: Recursive CTEs are a favorite for 'employee hierarchy' style questions in product-based companies — practice this pattern.

Q38. What are Window Functions in SQL?

Hard

Answer: Window functions perform calculations across a set of rows related to the current row (a 'window') without collapsing the result into a single row, using the OVER() clause. Examples include ROW_NUMBER(), RANK(), DENSE_RANK(), LAG(), LEAD(), and SUM() OVER().

Example Scenario: Show each employee's salary alongside the running total of salaries within their department.

SQL
SELECT emp_name, dept_id, salary,
SUM(salary) OVER (PARTITION BY dept_id ORDER BY emp_id) AS running_total
FROM Employees;
Output Explanation
Each row shows the individual salary plus a cumulative running total calculated within its own department.
💡 Interview Tip: Window functions are one of the most-tested advanced SQL topics in 2026 interviews — practice RANK vs DENSE_RANK vs ROW_NUMBER thoroughly.

Q39. What is the difference between RANK(), DENSE_RANK(), and ROW_NUMBER()?

Hard

Answer: ROW_NUMBER() assigns a unique sequential number to every row with no gaps or ties. RANK() assigns the same rank to tied rows but skips subsequent rank numbers. DENSE_RANK() also assigns the same rank to ties but does not skip the next rank number.

Example Scenario: Rank employees by salary within a department where two employees are tied for 2nd place.

SQL
SELECT emp_name, salary,
ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn,
RANK() OVER (ORDER BY salary DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY salary DESC) AS drnk
FROM Employees;
Output Explanation
For a tie at rank 2: ROW_NUMBER gives 2,3; RANK gives 2,2 then jumps to 4; DENSE_RANK gives 2,2 then continues at 3.
💡 Interview Tip: Draw this exact tie-scenario on paper before your interview — it's asked almost universally for window function rounds.

Q40. What are LAG() and LEAD() used for?

Hard

Answer: LAG() accesses data from a previous row and LEAD() accesses data from a following row within the same result set, without needing a self-join — useful for period-over-period comparisons.

Example Scenario: Compare each month's sales to the previous month's sales.

SQL
SELECT month, sales,
LAG(sales, 1) OVER (ORDER BY month) AS prev_month_sales
FROM MonthlySales;
Output Explanation
Each row shows the current month's sales next to the prior month's sales for easy month-over-month comparison.
💡 Interview Tip: Common real interview task: 'Calculate the difference between current and previous row' — combine LAG() with simple subtraction.

Q41. What is a View in SQL?

Medium

Answer: A View is a virtual table based on the result of a stored SELECT query. It doesn't store data itself (in most cases) but simplifies complex queries, and can restrict access to specific columns for security.

Example Scenario: Create a simplified view exposing only non-sensitive employee details.

SQL
CREATE VIEW EmployeePublic AS
SELECT emp_id, emp_name, dept_id FROM Employees;
Output Explanation
Users querying EmployeePublic see only emp_id, emp_name, and dept_id — sensitive columns like salary stay hidden.
💡 Interview Tip: Mention Materialized Views as a follow-up — they physically store data and need periodic refresh, unlike regular views.

Q42. What is an Index and why is it used?

Medium

Answer: An Index is a database object that improves the speed of data retrieval by creating a sorted structure (often a B-Tree) on one or more columns, at the cost of extra storage and slightly slower writes.

Example Scenario: Speed up searches on the email column, which is frequently filtered.

SQL
CREATE INDEX idx_employee_email ON Employees(email);
Output Explanation
Future queries filtering on email use the index to locate matching rows quickly, instead of scanning the whole table.
💡 Interview Tip: Always balance the answer: indexes speed up reads but slow down INSERT/UPDATE/DELETE due to index maintenance overhead.

Q43. What is a Stored Procedure?

Medium

Answer: A Stored Procedure is a precompiled, reusable block of SQL code stored in the database that can accept parameters, contain logic (loops, conditionals), and be called repeatedly by name.

Example Scenario: A procedure that gives a raise to all employees in a given department.

SQL
CREATE PROCEDURE GiveRaise (IN p_dept_id INT, IN p_amount DECIMAL(10,2))
BEGIN
  UPDATE Employees SET salary = salary + p_amount WHERE dept_id = p_dept_id;
END;
Output Explanation
Calling GiveRaise(3, 5000) increases the salary of every employee in department 3 by 5,000.
💡 Interview Tip: Highlight benefits: reusability, reduced network traffic, and centralized business logic — great talking points.

Q44. What is a Trigger in SQL?

Hard

Answer: A Trigger is a special stored procedure that automatically executes in response to specific events (INSERT, UPDATE, DELETE) on a table, often used for auditing or enforcing complex business rules.

Example Scenario: Automatically log every salary update into an audit table.

SQL
CREATE TRIGGER trg_salary_audit
AFTER UPDATE ON Employees
FOR EACH ROW
BEGIN
  INSERT INTO SalaryAudit(emp_id, old_salary, new_salary, changed_at)
  VALUES (OLD.emp_id, OLD.salary, NEW.salary, NOW());
END;
Output Explanation
Every time an employee's salary is updated, a new row automatically appears in SalaryAudit recording the change.
💡 Interview Tip: Mention risks: triggers can hide business logic and hurt performance if overused — show balanced judgment.

Q45. What is a Transaction in SQL?

Medium

Answer: A Transaction is a sequence of one or more SQL operations executed as a single logical unit of work — either all operations succeed (COMMIT) or none do (ROLLBACK), preserving data consistency.

Example Scenario: Transfer money between two bank accounts safely.

SQL
BEGIN TRANSACTION;
UPDATE Accounts SET balance = balance - 500 WHERE acct_id = 1;
UPDATE Accounts SET balance = balance + 500 WHERE acct_id = 2;
COMMIT;
Output Explanation
Both balance updates succeed together; if either statement fails, a ROLLBACK undoes both, so money is never lost mid-transfer.
💡 Interview Tip: Always tie transactions back to ACID properties in your answer — interviewers expect that connection.

Q46. What are the ACID properties in SQL?

Medium

Answer: ACID stands for Atomicity (all-or-nothing execution), Consistency (data moves from one valid state to another), Isolation (concurrent transactions don't interfere with each other), and Durability (once committed, changes survive system failures).

Example Scenario: A failed bank transfer transaction rolls back completely, leaving no partial update — demonstrating Atomicity.

SQL
-- Atomicity example
BEGIN TRANSACTION;
UPDATE Accounts SET balance = balance - 500 WHERE acct_id = 1;
-- error occurs here
ROLLBACK;
Output Explanation
The ROLLBACK undoes the debit entirely, so the account balance remains exactly as it was before the transaction started.
💡 Interview Tip: Have one crisp real-world example ready for each of the 4 letters — A, C, I, D — this is asked constantly.

Q47. What are the different Transaction Isolation Levels?

Hard

Answer: The four standard isolation levels are READ UNCOMMITTED (allows dirty reads), READ COMMITTED (prevents dirty reads), REPEATABLE READ (prevents dirty and non-repeatable reads), and SERIALIZABLE (strictest, prevents phantom reads too, at the cost of concurrency).

Example Scenario: An e-commerce checkout system might use REPEATABLE READ to avoid inconsistent stock counts mid-transaction.

SQL
SET TRANSACTION ISOLATION LEVEL REPEATABLE READ;
Output Explanation
Ensures that within the same transaction, repeated reads of the same row return identical results even if other transactions modify it concurrently.
💡 Interview Tip: Be ready to explain dirty read, non-repeatable read, and phantom read with one-sentence examples each.

Q48. What is the difference between COMMIT, ROLLBACK, and SAVEPOINT?

Hard

Answer: COMMIT permanently saves all changes made during the current transaction. ROLLBACK undoes changes made since the last COMMIT (or SAVEPOINT). SAVEPOINT sets a named point within a transaction that you can roll back to without undoing the entire transaction.

Example Scenario: Roll back only part of a multi-step transaction using a savepoint.

SQL
BEGIN TRANSACTION;
UPDATE Employees SET salary = salary + 1000 WHERE dept_id = 1;
SAVEPOINT sp1;
UPDATE Employees SET salary = salary + 2000 WHERE dept_id = 2;
ROLLBACK TO sp1;
COMMIT;
Output Explanation
The dept_id = 2 raise is undone by the rollback to sp1, but the dept_id = 1 raise is kept and permanently saved by COMMIT.
💡 Interview Tip: SAVEPOINT questions test if you understand partial rollback — a strong answer here signals real transaction experience.

Q49. What is Denormalization and when would you use it?

Medium

Answer: Denormalization intentionally introduces controlled redundancy into a normalized schema to reduce the number of joins needed, improving read performance for reporting or analytics-heavy workloads at the cost of some data duplication.

Example Scenario: A reporting dashboard table stores a pre-joined, flattened combination of Orders, Customers, and Products for faster queries.

SQL
CREATE TABLE SalesReportFlat AS
SELECT o.order_id, c.cust_name, p.product_name, o.quantity, o.order_date
FROM Orders o JOIN Customers c ON o.cust_id = c.cust_id JOIN Products p ON o.product_id = p.product_id;
Output Explanation
Creates a single flat table that analysts can query directly without repeatedly joining three normalized tables.
💡 Interview Tip: Say denormalization is a deliberate trade-off for read speed in OLAP/reporting systems, not a mistake — shows maturity.

Q50. What is the difference between OLTP and OLAP?

Medium

Answer: OLTP (Online Transaction Processing) systems handle many short, frequent read/write transactions, like order processing, and favor normalized schemas. OLAP (Online Analytical Processing) systems handle complex analytical queries over large historical datasets and favor denormalized, star/snowflake schemas.

Example Scenario: An e-commerce checkout database is OLTP; a sales analytics warehouse summarizing years of orders is OLAP.

SQL
-- OLTP: fast single-row insert
INSERT INTO Orders (cust_id, product_id, quantity) VALUES (101, 5, 2);
-- OLAP: heavy aggregate query
SELECT product_id, SUM(quantity) FROM Orders GROUP BY product_id;
Output Explanation
The OLTP insert completes in milliseconds for one transaction; the OLAP query scans and aggregates millions of historical rows.
💡 Interview Tip: Data analyst interviews frequently pair this with 'what is a data warehouse/star schema' — be ready to extend the answer.

Q61. What is the difference between DROP, TRUNCATE, and DELETE in terms of rollback?

Medium

Answer: DELETE is fully logged and can be rolled back within a transaction. TRUNCATE is minimally logged and, in most databases, cannot be rolled back once committed (though some databases allow it inside an explicit transaction). DROP removes the object entirely and generally cannot be rolled back after commit.

Example Scenario: Accidentally truncating a production table without a transaction wrapper.

SQL
-- Safer approach
BEGIN TRANSACTION;
TRUNCATE TABLE Orders;
-- verify before committing
ROLLBACK;
Output Explanation
Depending on the database, wrapping TRUNCATE in an explicit transaction may allow you to roll it back before commit — but don't rely on this everywhere.
💡 Interview Tip: Always mention taking a backup or wrapping risky DDL/TRUNCATE statements in a transaction where supported — shows production discipline.

Q62. What is a Deadlock and how can it be avoided?

Hard

Answer: A Deadlock occurs when two or more transactions hold locks that the other transactions need, creating a cycle where none can proceed. It can be avoided by accessing tables in a consistent order, keeping transactions short, and using appropriate isolation levels.

Example Scenario: Transaction A locks Table1 then waits for Table2, while Transaction B locks Table2 then waits for Table1.

SQL
-- Best practice: always update tables in the same order
BEGIN TRANSACTION;
UPDATE Accounts SET balance = balance - 100 WHERE acct_id = 1;
UPDATE Accounts SET balance = balance + 100 WHERE acct_id = 2;
COMMIT;
Output Explanation
By always locking accounts in ascending acct_id order across all transactions, circular waiting is prevented.
💡 Interview Tip: Mention that most databases automatically detect deadlocks and kill one transaction as a 'victim' — show you understand the recovery mechanism too.

Q63. What is the difference between a Function and a Stored Procedure?

Medium

Answer: A Function must return a single value (or table) and can be used inside a SELECT statement, but cannot modify data or use transaction control statements in most databases. A Stored Procedure can perform DML/DDL operations, doesn't have to return a value, and is called independently, not embedded in a query.

Example Scenario: A function to calculate bonus vs a procedure to apply that bonus to all employees.

SQL
CREATE FUNCTION CalcBonus(salary DECIMAL) RETURNS DECIMAL
RETURN salary * 0.10;
Output Explanation
CalcBonus can be used directly inside a SELECT statement like SELECT emp_name, CalcBonus(salary) FROM Employees.
💡 Interview Tip: Interviewers like the phrase: 'Functions compute and return; procedures perform and act' — a clean one-liner.

Q64. What is the purpose of the EXPLAIN / EXPLAIN PLAN statement?

Hard

Answer: EXPLAIN shows the database's query execution plan — how it intends to scan tables, use indexes, join data, and estimate cost — helping developers identify performance bottlenecks before optimizing a query.

Example Scenario: Diagnose why a query filtering on email is slow.

SQL
EXPLAIN SELECT * FROM Customers WHERE email = 'test@example.com';
Output Explanation
The output reveals whether the database performs a full table scan or uses an index, along with estimated row counts and cost.
💡 Interview Tip: Always mention 'seq scan vs index scan' — spotting a full table scan on a large table in an EXPLAIN plan is a key optimization skill.

Q65. What is Query Optimization? Name a few techniques.

Medium

Answer: Query optimization is the process of rewriting or restructuring SQL to reduce execution time and resource usage. Techniques include adding proper indexes, avoiding SELECT *, using JOINs instead of correlated subqueries where possible, filtering early, and analyzing execution plans.

Example Scenario: Replacing SELECT * with only the needed columns to reduce I/O.

SQL
-- Before
SELECT * FROM Orders WHERE cust_id = 101;
-- After
SELECT order_id, order_date, amount FROM Orders WHERE cust_id = 101;
Output Explanation
The optimized query retrieves only necessary columns, reducing data transfer and memory usage, especially on wide tables.
💡 Interview Tip: Have 5 optimization techniques memorized as a checklist — this open-ended question is asked in almost every senior-level round.

Q66. Why should you avoid SELECT * in production queries?

Easy

Answer: SELECT * retrieves all columns even if unnecessary, increasing I/O, network transfer, and memory usage. It also breaks if the table schema changes and makes queries harder to read, plus it can prevent the optimizer from using covering indexes efficiently.

Example Scenario: A report only needs emp_name and salary but uses SELECT *, unnecessarily pulling large text/blob columns too.

SQL
SELECT emp_name, salary FROM Employees;
Output Explanation
Retrieves only the two required columns, reducing data transferred and allowing potential use of a covering index.
💡 Interview Tip: This is a rapid-fire favorite — always have this answer ready in under 10 seconds.

Q67. What is a Covering Index?

Hard

Answer: A Covering Index includes all the columns a query needs, so the database can satisfy the query entirely from the index without accessing the actual table data, significantly improving performance.

Example Scenario: A query that filters by dept_id and selects only emp_name can be fully served by an index on (dept_id, emp_name).

SQL
CREATE INDEX idx_dept_name ON Employees(dept_id, emp_name);
Output Explanation
The query SELECT emp_name FROM Employees WHERE dept_id = 3 can be answered directly from the index, skipping table lookups entirely.
💡 Interview Tip: Bring this up unprompted when discussing indexing strategy — it signals advanced, real-world performance tuning knowledge.

Q68. When should you avoid creating too many indexes?

Hard

Answer: Excessive indexing slows down INSERT, UPDATE, and DELETE operations because every index must be updated alongside the data, and it increases storage overhead. Indexes should be created based on actual query patterns, not preemptively on every column.

Example Scenario: A heavily-written logging table with 10 indexes suffers slow inserts during peak traffic.

SQL
-- Review and drop unused indexes
DROP INDEX idx_unused_column ON LogTable;
Output Explanation
Removing an unused index reduces write overhead on every future insert into LogTable.
💡 Interview Tip: Mention using query logs / index usage statistics to identify and drop unused indexes — a real DBA-level insight.

Q69. What is Index Fragmentation and how do you fix it?

Hard

Answer: Index Fragmentation happens when data pages become disorganized due to frequent inserts, updates, and deletes, causing the index to no longer be stored in optimal contiguous order, which slows down reads. It's fixed by rebuilding or reorganizing the index periodically.

Example Scenario: A frequently updated Orders table gradually develops fragmented indexes over months.

SQL
ALTER INDEX idx_orders_date ON Orders REBUILD;
Output Explanation
Rebuilding the index restores it to a clean, contiguous structure, restoring optimal read performance.
💡 Interview Tip: Mention this is typically a scheduled DBA maintenance task, not something run ad hoc during business hours.

Q70. How would you optimize a slow query with multiple JOINs?

Hard

Answer: Check the execution plan for full table scans, ensure join columns are indexed (especially foreign keys), filter data as early as possible with WHERE before joining large tables, avoid unnecessary columns, and consider breaking the query into smaller steps or using temp tables for very complex logic.

Example Scenario: A report joining Orders, Customers, and Products runs slowly.

SQL
-- Ensure indexes exist on join keys
CREATE INDEX idx_orders_cust ON Orders(cust_id);
CREATE INDEX idx_orders_prod ON Orders(product_id);
Output Explanation
Adding indexes on the foreign key columns used in JOIN conditions lets the optimizer avoid full scans on Orders.
💡 Interview Tip: Structure your answer as a checklist (indexes → filters → execution plan → schema) — interviewers reward a systematic approach.

Q71. What is Partitioning in databases?

Hard

Answer: Partitioning splits a large table into smaller, more manageable physical segments (by range, list, or hash) while still being queried as one logical table, improving performance and maintenance for very large datasets.

Example Scenario: Partition a Sales table by year so queries filtering on recent years scan far less data.

SQL
CREATE TABLE Sales (sale_id INT, sale_date DATE, amount DECIMAL)
PARTITION BY RANGE (YEAR(sale_date)) (
  PARTITION p2024 VALUES LESS THAN (2025),
  PARTITION p2025 VALUES LESS THAN (2026)
);
Output Explanation
A query filtering WHERE sale_date >= '2025-01-01' only scans the p2025 partition instead of the entire table.
💡 Interview Tip: Mention partition pruning explicitly — it's the exact term interviewers listen for when discussing partitioning benefits.

Q72. What is the difference between a Temporary Table and a CTE?

Medium

Answer: A Temporary Table physically stores data for the session/transaction and can be indexed and reused across multiple statements. A CTE exists only for the duration of a single query, is not indexed, and is generally re-evaluated each time it's referenced.

Example Scenario: Reusing intermediate results across several queries in a session vs. simplifying one complex query.

SQL
CREATE TEMPORARY TABLE TempHighEarners AS
SELECT * FROM Employees WHERE salary > 80000;
Output Explanation
TempHighEarners can now be queried multiple times within the session without recomputing the filter each time.
💡 Interview Tip: Say CTEs improve readability for a single query, while temp tables are better when you need to reuse or index intermediate results.

Q73. What is the difference between UNION and JOIN?

Easy

Answer: JOIN combines columns from two tables side by side based on a related column. UNION stacks rows from two queries vertically, requiring the same number of columns and compatible data types in both queries.

Example Scenario: Combine two lists of names (UNION) vs. combining employee and department details (JOIN).

SQL
SELECT emp_name FROM Employees
UNION
SELECT cust_name FROM Customers;
Output Explanation
Produces a single stacked list combining names from both tables, with duplicates removed.
💡 Interview Tip: Simple analogy: 'JOIN adds columns, UNION adds rows' — a quick memorable line for interviews.

Q74. What are Set Operators in SQL besides UNION?

Medium

Answer: Besides UNION and UNION ALL, SQL supports INTERSECT (returns only rows common to both queries) and EXCEPT/MINUS (returns rows in the first query that are not in the second).

Example Scenario: Find customers who placed orders in both 2024 and 2025.

SQL
SELECT cust_id FROM Orders WHERE YEAR(order_date) = 2024
INTERSECT
SELECT cust_id FROM Orders WHERE YEAR(order_date) = 2025;
Output Explanation
Returns only customer IDs that appear in both the 2024 and 2025 order lists.
💡 Interview Tip: Note MySQL added native INTERSECT/EXCEPT support in recent versions — mention checking your specific database version.

Data Analyst SQL Interview Questions

Q51. How do you find the second highest salary in a table?

Medium

Answer: Use a subquery with LIMIT/OFFSET, or DISTINCT with ORDER BY and OFFSET, or a window function like DENSE_RANK() to skip the top value and get the next distinct one.

Example Scenario: Find the second highest salary in Employees.

SQL
SELECT DISTINCT salary FROM Employees ORDER BY salary DESC LIMIT 1 OFFSET 1;
Output Explanation
Skips the highest salary (offset 1) and returns the next distinct highest value.
💡 Interview Tip: Also know the MAX() subquery version: SELECT MAX(salary) FROM Employees WHERE salary < (SELECT MAX(salary) FROM Employees) — some interviewers specifically want this pattern.

Q52. How do you find duplicate records in a table?

Medium

Answer: Group by the columns that should be unique, then use HAVING COUNT(*) > 1 to find groups that appear more than once.

Example Scenario: Find duplicate email addresses in the Customers table.

SQL
SELECT email, COUNT(*) AS cnt FROM Customers GROUP BY email HAVING COUNT(*) > 1;
Output Explanation
Returns each duplicated email along with how many times it appears, so you can investigate or clean the data.
💡 Interview Tip: Follow-up almost always asked: 'now delete the duplicates keeping only one' — practice that pattern using ROW_NUMBER() with a CTE.

Q53. How do you delete duplicate rows but keep one copy?

Hard

Answer: Use a CTE with ROW_NUMBER() partitioned by the duplicate-defining columns, then delete rows where the row number is greater than 1.

Example Scenario: Remove duplicate customer emails, keeping the earliest inserted row.

SQL
WITH Ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY email ORDER BY cust_id) AS rn
  FROM Customers
)
DELETE FROM Ranked WHERE rn > 1;
Output Explanation
Keeps the first occurrence (rn = 1) of each email and removes every later duplicate row.
💡 Interview Tip: This exact pattern — CTE + ROW_NUMBER + DELETE — is one of the highest-frequency practical SQL interview questions.

Q54. How do you find the Nth highest salary generically?

Hard

Answer: Use DENSE_RANK() in a CTE or subquery, then filter WHERE rank = N — this correctly handles ties, unlike LIMIT/OFFSET approaches.

Example Scenario: Find the 3rd highest distinct salary.

SQL
WITH RankedSalary AS (
  SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk
  FROM Employees
)
SELECT DISTINCT salary FROM RankedSalary WHERE rnk = 3;
Output Explanation
Returns the salary value that ranks 3rd among distinct salary values, correctly skipping duplicate rank ties.
💡 Interview Tip: Explicitly say why DENSE_RANK is safer than OFFSET when duplicate salaries exist — this nuance impresses interviewers.

Q55. How do you calculate a running total (cumulative sum)?

Hard

Answer: Use SUM() as a window function with ORDER BY inside OVER() to accumulate values row by row within a defined order (and optional partition).

Example Scenario: Calculate cumulative sales for each day in a Sales table.

SQL
SELECT sale_date, amount,
SUM(amount) OVER (ORDER BY sale_date) AS running_total
FROM Sales;
Output Explanation
Each row shows that day's sale amount plus the sum of all sales up to and including that date.
💡 Interview Tip: Running totals and moving averages are extremely common in data analyst take-home tests — practice both.

Q56. How do you calculate a moving average in SQL?

Hard

Answer: Use AVG() as a window function with a ROWS BETWEEN frame to define how many preceding/following rows to include in each average calculation.

Example Scenario: Calculate a 3-day moving average of sales.

SQL
SELECT sale_date, amount,
AVG(amount) OVER (ORDER BY sale_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS moving_avg_3day
FROM Sales;
Output Explanation
Each row's moving average is calculated from the current day plus the two preceding days.
💡 Interview Tip: Explain ROWS BETWEEN framing clearly — it's the piece most candidates fumble under interview pressure.

Q57. How do you find customers who have never placed an order?

Medium

Answer: Use a LEFT JOIN from Customers to Orders and filter where the Orders key is NULL, or use a NOT IN / NOT EXISTS subquery.

Example Scenario: Identify customers with zero orders for a re-engagement email campaign.

SQL
SELECT c.cust_id, c.cust_name FROM Customers c
LEFT JOIN Orders o ON c.cust_id = o.cust_id
WHERE o.order_id IS NULL;
Output Explanation
Returns only customers who have no matching row at all in the Orders table.
💡 Interview Tip: Mention NOT EXISTS as a generally safer alternative to NOT IN when the subquery column can contain NULLs.

Q58. What is the difference between NOT IN and NOT EXISTS?

Hard

Answer: NOT IN can behave unexpectedly and return zero rows if the subquery's result set contains even one NULL value. NOT EXISTS uses a correlated existence check and handles NULLs safely, making it generally the more reliable choice.

Example Scenario: Find employees whose dept_id is not present in a Departments list that might contain a NULL.

SQL
SELECT emp_name FROM Employees e
WHERE NOT EXISTS (SELECT 1 FROM Departments d WHERE d.dept_id = e.dept_id);
Output Explanation
Correctly returns employees with no matching department, even if the Departments table has NULL dept_id values elsewhere.
💡 Interview Tip: This is a favorite 'gotcha' interview question — always recommend NOT EXISTS over NOT IN for safety.

Q59. How do you pivot rows into columns in SQL?

Hard

Answer: Use conditional aggregation with CASE WHEN inside SUM()/COUNT(), or a database-specific PIVOT operator, to transform row values into separate columns.

Example Scenario: Show total sales per product as separate columns for each quarter.

SQL
SELECT product_id,
SUM(CASE WHEN quarter = 'Q1' THEN sales ELSE 0 END) AS Q1_sales,
SUM(CASE WHEN quarter = 'Q2' THEN sales ELSE 0 END) AS Q2_sales
FROM QuarterlySales GROUP BY product_id;
Output Explanation
Returns one row per product with separate columns for Q1 and Q2 sales instead of separate rows per quarter.
💡 Interview Tip: CASE WHEN + SUM() pivoting is the most portable technique across databases — safer to mention than vendor-specific PIVOT syntax.

Q60. How would you find students who scored above the class average in each subject?

Hard

Answer: Use a correlated subquery or window function (AVG() OVER PARTITION BY subject) to compare each student's marks to the average for their specific subject.

Example Scenario: Using a Students/Marks table, find students scoring above their subject's average.

SQL
SELECT student_id, subject, marks FROM (
  SELECT student_id, subject, marks,
  AVG(marks) OVER (PARTITION BY subject) AS subj_avg
  FROM Marks
) t WHERE marks > subj_avg;
Output Explanation
Returns only student-subject rows where the individual score beats the average score for that particular subject.
💡 Interview Tip: Window functions inside a derived table/subquery are a clean pattern — practice writing it fluently without hesitation.

Q75. How would you find the department with the highest average salary?

Medium

Answer: Group employees by department, calculate the average salary per group, then order descending and limit to the top result (or use a subquery/window function to handle ties).

Example Scenario: Identify the top-paying department for a compensation benchmarking report.

SQL
SELECT dept_id, AVG(salary) AS avg_salary FROM Employees
GROUP BY dept_id ORDER BY avg_salary DESC LIMIT 1;
Output Explanation
Returns the single department with the highest average salary across its employees.
💡 Interview Tip: Ask the interviewer if ties should be handled — showing that consideration is itself a strong signal.

Q76. How do you find employees who earn more than their manager?

Medium

Answer: Self-join the Employees table so each employee row is matched with their manager's row (via manager_id = emp_id), then filter where the employee's salary exceeds the manager's salary.

Example Scenario: A classic 'employee earns more than boss' interview question.

SQL
SELECT e.emp_name AS employee, e.salary AS emp_salary, m.salary AS mgr_salary
FROM Employees e JOIN Employees m ON e.manager_id = m.emp_id
WHERE e.salary > m.salary;
Output Explanation
Returns only employees whose individual salary is higher than the salary of the manager they report to.
💡 Interview Tip: This exact question appears on nearly every 'famous SQL interview questions' list — practice it until it's automatic.

Q77. How do you calculate percentage contribution of each product to total sales?

Hard

Answer: Divide each product's total sales by the overall total sales (using a window function SUM() OVER() with no partition, or a subquery for the grand total), then multiply by 100.

Example Scenario: Show each product's share of total company revenue.

SQL
SELECT product_id, SUM(amount) AS product_sales,
ROUND(SUM(amount) * 100.0 / SUM(SUM(amount)) OVER (), 2) AS pct_of_total
FROM Orders GROUP BY product_id;
Output Explanation
Each row shows a product's total sales and what percentage that represents of overall company sales.
💡 Interview Tip: Watch out for integer division — always multiply by 100.0 (a decimal) to avoid truncated zero results in some databases.

Q78. How do you find the top 3 products by sales in each category?

Hard

Answer: Use ROW_NUMBER() or DENSE_RANK() partitioned by category, ordered by total sales descending, inside a CTE, then filter for rank <= 3.

Example Scenario: A merchandising team wants the top 3 best-selling products per category.

SQL
WITH RankedProducts AS (
  SELECT category, product_name, SUM(quantity) AS total_qty,
  ROW_NUMBER() OVER (PARTITION BY category ORDER BY SUM(quantity) DESC) AS rnk
  FROM Orders o JOIN Products p ON o.product_id = p.product_id
  GROUP BY category, product_name
)
SELECT * FROM RankedProducts WHERE rnk <= 3;
Output Explanation
Returns exactly the top 3 best-selling products within each product category, ranked by total quantity sold.
💡 Interview Tip: This 'top-N per group' pattern is arguably the single most common real-world SQL interview question — master it cold.

Q79. How would you detect month-over-month growth rate in sales?

Hard

Answer: Use LAG() to fetch the previous month's total, then calculate the percentage change between the current and previous month.

Example Scenario: Report monthly sales growth rate for a business dashboard.

SQL
SELECT month, total_sales,
ROUND((total_sales - LAG(total_sales) OVER (ORDER BY month)) * 100.0
  / LAG(total_sales) OVER (ORDER BY month), 2) AS growth_pct
FROM MonthlySales;
Output Explanation
Each row shows the percentage increase or decrease in sales compared to the immediately preceding month.
💡 Interview Tip: Mention handling the first row's NULL growth value gracefully (e.g., with COALESCE) — attention to edge cases stands out.

Q80. How do you find gaps in a sequence of numbers (e.g., missing order IDs)?

Hard

Answer: Compare each value to the next expected value using LEAD() or a self-join, and flag rows where the difference is greater than 1, indicating a gap in the sequence.

Example Scenario: Identify missing order_id values in an Orders table for data quality checks.

SQL
SELECT order_id, LEAD(order_id) OVER (ORDER BY order_id) - order_id AS gap
FROM Orders
HAVING gap > 1;
Output Explanation
Rows where 'gap' is greater than 1 indicate a missing order_id between the current and next value.
💡 Interview Tip: 'Gaps and islands' problems are a well-known SQL interview category — worth practicing beyond just this basic version.

Real-World SQL Scenario-Based Interview Questions

Q81. Write a query to swap the values of two columns without using a temporary variable.

Medium

Answer: Use simultaneous assignment in a single UPDATE statement so both columns are swapped using their original values in one pass.

Example Scenario: Swap salary and bonus columns for all employees.

SQL
UPDATE Employees SET salary = bonus, bonus = salary;
Output Explanation
In most databases this evaluates the right-hand side expressions before applying updates, correctly swapping both values in a single statement.
💡 Interview Tip: Double-check your specific database's evaluation order — a few databases require a CASE-based swap instead to guarantee correctness.

Q82. How would you find employees hired in the last 30 days?

Easy

Answer: Compare the hire_date column to the current date minus 30 days using date functions, filtering with WHERE.

Example Scenario: HR wants a report of very recent hires.

SQL
SELECT emp_name, hire_date FROM Employees WHERE hire_date >= CURRENT_DATE - INTERVAL '30 days';
Output Explanation
Returns only employees whose hire_date falls within the past 30 days from today.
💡 Interview Tip: Know your database's date syntax variants (DATEADD in SQL Server, INTERVAL in PostgreSQL/MySQL) — mention you'd check documentation for the exact dialect.

Q83. How do you find the total number of orders placed by each customer, including customers with zero orders?

Medium

Answer: LEFT JOIN Customers to Orders and use COUNT() on the Orders key (not COUNT(*)), so customers with no matching orders correctly show 0 instead of being excluded.

Example Scenario: A CRM report needs every customer represented, even inactive ones.

SQL
SELECT c.cust_name, COUNT(o.order_id) AS total_orders
FROM Customers c LEFT JOIN Orders o ON c.cust_id = o.cust_id
GROUP BY c.cust_name;
Output Explanation
Every customer appears in the result; customers with no orders show a count of 0 instead of being dropped.
💡 Interview Tip: The classic mistake here is using COUNT(*) instead of COUNT(o.order_id) — COUNT(*) would incorrectly show 1 for customers with no matching orders.

Q84. How would you find the maximum salary in each department along with the employee name?

Hard

Answer: Use a window function MAX() OVER(PARTITION BY dept_id) to compute department max alongside each row, then filter where salary equals that max, or use a correlated subquery.

Example Scenario: HR wants to know the top earner in every department.

SQL
SELECT emp_name, dept_id, salary FROM (
  SELECT emp_name, dept_id, salary,
  MAX(salary) OVER (PARTITION BY dept_id) AS max_sal
  FROM Employees
) t WHERE salary = max_sal;
Output Explanation
Returns the highest-paid employee(s) in each department, correctly including ties if two employees share the top salary.
💡 Interview Tip: This approach naturally handles ties, unlike a simple GROUP BY MAX(salary) which would lose the emp_name column.

Q85. How do you update a column value only if a condition is met across a join?

Medium

Answer: Use an UPDATE statement with a JOIN (or a correlated subquery, depending on the database) so the update logic can reference columns from a related table.

Example Scenario: Increase salary by 10% for employees in the 'Sales' department.

SQL
UPDATE Employees e
JOIN Departments d ON e.dept_id = d.dept_id
SET e.salary = e.salary * 1.10
WHERE d.dept_name = 'Sales';
Output Explanation
Only employees belonging to the Sales department receive the 10% salary increase; all others remain unchanged.
💡 Interview Tip: Mention that standard SQL/PostgreSQL uses UPDATE ... FROM syntax instead of UPDATE ... JOIN — know both dialect variations.

Q86. How would you find products that have never been ordered?

Medium

Answer: LEFT JOIN Products to Orders and filter for rows where the Orders key is NULL, indicating no matching order exists for that product.

Example Scenario: Inventory team wants to identify dead stock.

SQL
SELECT p.product_id, p.product_name FROM Products p
LEFT JOIN Orders o ON p.product_id = o.product_id
WHERE o.order_id IS NULL;
Output Explanation
Returns only products that have zero matching rows in the Orders table.
💡 Interview Tip: This is structurally identical to the 'customers with no orders' pattern — recognizing reusable patterns saves time under pressure.

Q87. How do you find consecutive days a customer has placed orders (a streak)?

Hard

Answer: Use the 'gaps and islands' technique: subtract a row number (via ROW_NUMBER ordered by date) from the actual date; consecutive dates produce the same difference, which can then be grouped to find streaks.

Example Scenario: Identify a customer's longest consecutive daily ordering streak for a loyalty program.

SQL
WITH Ordered AS (
  SELECT cust_id, order_date,
  order_date - ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY order_date) * INTERVAL '1 day' AS grp
  FROM Orders
)
SELECT cust_id, grp, COUNT(*) AS streak_days
FROM Ordered GROUP BY cust_id, grp;
Output Explanation
Rows sharing the same 'grp' value represent one unbroken streak of consecutive order dates for that customer.
💡 Interview Tip: This is a genuinely hard, senior-level pattern — mentioning you know 'gaps and islands' by name alone earns credibility even if you need a moment to derive it.

Q88. How would you find the median salary in a department using SQL?

Hard

Answer: Use PERCENTILE_CONT(0.5) as a window/aggregate function if supported, or manually rank rows and average the middle value(s) for odd/even row counts.

Example Scenario: HR wants the median (not average) salary per department to avoid outlier skew.

SQL
SELECT dept_id,
PERCENTILE_CONT(0.5) WITHIN GROUP (ORDER BY salary) OVER (PARTITION BY dept_id) AS median_salary
FROM Employees;
Output Explanation
Returns the true middle salary value for each department, unaffected by extremely high or low outlier salaries.
💡 Interview Tip: If PERCENTILE_CONT isn't available (e.g., older MySQL), mention the manual ROW_NUMBER + AVG-of-middle-rows fallback approach.

Q89. How do you handle NULL values when calculating an average?

Medium

Answer: AVG() automatically ignores NULL values in its calculation by default — it does not treat them as zero. To include them as zero explicitly, wrap the column with COALESCE(column, 0) first.

Example Scenario: Calculate average bonus where some employees have no bonus recorded (NULL) versus employees with an actual 0 bonus.

SQL
SELECT AVG(bonus) AS avg_ignoring_null, AVG(COALESCE(bonus, 0)) AS avg_treating_null_as_zero
FROM Employees;
Output Explanation
The first average excludes NULL rows entirely from both sum and count; the second treats every NULL as 0, lowering the result.
💡 Interview Tip: This distinction trips up many candidates — always clarify which behavior the business actually wants before writing the query.

Q90. How would you compare this month's active users to last month's using SQL?

Hard

Answer: Aggregate distinct users per month, then use a self-join or LAG() across the monthly aggregated table to compare counts month over month.

Example Scenario: A product analytics team tracks month-over-month active user retention.

SQL
WITH Monthly AS (
  SELECT DATE_TRUNC('month', activity_date) AS month, COUNT(DISTINCT user_id) AS active_users
  FROM UserActivity GROUP BY 1
)
SELECT month, active_users, LAG(active_users) OVER (ORDER BY month) AS prev_month_users
FROM Monthly;
Output Explanation
Each row shows the current month's active user count alongside the previous month's count for direct comparison.
💡 Interview Tip: Data analyst interviews often extend this into retention/cohort analysis — be ready to discuss that natural next step.

Q91. How do you safely archive old records before deleting them?

Medium

Answer: Insert the qualifying rows into an archive table first, verify the insert succeeded, and only then delete them from the original table — ideally wrapped in a single transaction for safety.

Example Scenario: Move orders older than 3 years into an OrdersArchive table.

SQL
BEGIN TRANSACTION;
INSERT INTO OrdersArchive SELECT * FROM Orders WHERE order_date < CURRENT_DATE - INTERVAL '3 years';
DELETE FROM Orders WHERE order_date < CURRENT_DATE - INTERVAL '3 years';
COMMIT;
Output Explanation
Old orders are copied into the archive table and removed from the live table in one atomic transaction, so a failure leaves neither table inconsistently changed.
💡 Interview Tip: Emphasize the transaction wrapper — doing insert and delete as two separate uncommitted statements risks data loss on failure.

Q92. How would you find overlapping date ranges (e.g., overlapping bookings)?

Hard

Answer: Two ranges overlap when one range's start is before the other's end AND its end is after the other's start — this condition can be checked with a self-join on that logic.

Example Scenario: A hotel booking system needs to detect double-booked rooms.

SQL
SELECT a.booking_id, b.booking_id FROM Bookings a
JOIN Bookings b ON a.room_id = b.room_id AND a.booking_id < b.booking_id
WHERE a.start_date < b.end_date AND a.end_date > b.start_date;
Output Explanation
Returns pairs of bookings for the same room whose date ranges overlap, flagging a scheduling conflict.
💡 Interview Tip: Memorize this exact overlap condition (start1 < end2 AND end1 > start2) — deriving it live under pressure is much harder.

Q93. How do you calculate the difference in days between two dates?

Easy

Answer: Use DATEDIFF() (SQL Server/MySQL) or simple subtraction of DATE types (PostgreSQL) to get the number of days between two date values.

Example Scenario: Calculate how many days each order took to ship.

SQL
SELECT order_id, DATEDIFF(ship_date, order_date) AS days_to_ship FROM Orders;
Output Explanation
Returns the number of calendar days between the order date and the ship date for every order.
💡 Interview Tip: Mention the function name differs by database (DATEDIFF, AGE, or plain subtraction) — show dialect awareness.

Q94. How do you find the first and last order date for each customer?

Easy

Answer: Use MIN() and MAX() aggregate functions on the order date column, grouped by customer.

Example Scenario: Understand customer lifecycle by finding their first and most recent purchase.

SQL
SELECT cust_id, MIN(order_date) AS first_order, MAX(order_date) AS last_order
FROM Orders GROUP BY cust_id;
Output Explanation
Returns one row per customer showing their earliest and most recent order dates.
💡 Interview Tip: A natural follow-up is calculating customer lifetime in days — be ready to extend with DATEDIFF(MAX, MIN).

Q95. How would you find students who failed in all subjects using a Marks table?

Medium

Answer: Group by student, and use a HAVING clause with conditional aggregation (e.g., SUM of a CASE WHEN passing) to ensure every single subject was below the passing threshold.

Example Scenario: Using a Students/Marks table, flag students who failed every subject they took.

SQL
SELECT student_id FROM Marks
GROUP BY student_id
HAVING SUM(CASE WHEN marks >= 40 THEN 1 ELSE 0 END) = 0;
Output Explanation
Returns only students where the count of passing subjects (marks >= 40) is exactly zero, meaning they failed everything.
💡 Interview Tip: Contrast this with 'failed in at least one subject' (HAVING SUM(...) < COUNT(*)) — interviewers often ask both variants back to back.

Q96. How do you find the class topper (highest total marks) per class/section?

Hard

Answer: Sum marks per student, then rank students within each class/section using RANK() or ROW_NUMBER() and filter for the top rank.

Example Scenario: Using Students and Marks tables, find the topper of each section.

SQL
WITH Totals AS (
  SELECT s.section, s.student_id, SUM(m.marks) AS total_marks
  FROM Students s JOIN Marks m ON s.student_id = m.student_id
  GROUP BY s.section, s.student_id
),
Ranked AS (
  SELECT *, RANK() OVER (PARTITION BY section ORDER BY total_marks DESC) AS rnk FROM Totals
)
SELECT * FROM Ranked WHERE rnk = 1;
Output Explanation
Returns the student (or tied students) with the highest total marks within each section.
💡 Interview Tip: This layered CTE approach (aggregate → rank → filter) is a reusable template for many 'top performer per group' questions.

Q97. What is the difference between a Data Warehouse and a Database?

Medium

Answer: A Database is typically optimized for OLTP — fast, transactional, day-to-day operations on current data. A Data Warehouse is optimized for OLAP — storing large volumes of historical, integrated data from multiple sources for analysis and reporting, usually using denormalized star/snowflake schemas.

Example Scenario: A retail company's live order system is a database; its multi-year sales analytics platform is a data warehouse.

SQL
-- Data warehouse fact table example
CREATE TABLE FactSales (sale_id INT, date_key INT, product_key INT, customer_key INT, amount DECIMAL);
Output Explanation
The fact table stores pre-aggregated, denormalized sales data optimized for fast analytical queries across time, product, and customer dimensions.
💡 Interview Tip: Data analyst interviews often pair this with 'what is a star schema vs snowflake schema' — have a one-line distinction ready.

Q98. How would you validate data quality using SQL (e.g., checking referential integrity manually)?

Medium

Answer: Write queries that check for orphan foreign keys, unexpected NULLs in required fields, duplicate primary keys, or values outside expected ranges/formats, often combined into a data quality checklist run periodically.

Example Scenario: Check for Orders referencing a cust_id that doesn't exist in Customers.

SQL
SELECT o.order_id, o.cust_id FROM Orders o
LEFT JOIN Customers c ON o.cust_id = c.cust_id
WHERE c.cust_id IS NULL;
Output Explanation
Returns any orphan orders whose cust_id has no matching row in Customers, signaling a referential integrity issue.
💡 Interview Tip: Data analyst roles increasingly expect basic data-quality SQL — mention you'd automate such checks as scheduled validation queries.

Q99. How do you find the second most recent order for each customer?

Hard

Answer: Use ROW_NUMBER() partitioned by customer and ordered by order date descending, then filter for row number equal to 2.

Example Scenario: A marketing team wants each customer's second-most-recent purchase for a re-engagement campaign.

SQL
WITH Ranked AS (
  SELECT *, ROW_NUMBER() OVER (PARTITION BY cust_id ORDER BY order_date DESC) AS rn
  FROM Orders
)
SELECT * FROM Ranked WHERE rn = 2;
Output Explanation
Returns exactly one row per customer — their second-most-recent order, based on descending order date.
💡 Interview Tip: This 'Nth row per group' pattern using ROW_NUMBER is one of the highest-value templates to memorize for interviews.

Q100. How would you design a query to detect salary outliers in a department?

Hard

Answer: Calculate the department's average and standard deviation of salary, then flag employees whose salary falls beyond a chosen number of standard deviations (e.g., 2) from the mean.

Example Scenario: HR compliance wants to flag unusually high or low salaries within each department for review.

SQL
SELECT e.emp_name, e.salary, d.avg_sal, d.stddev_sal
FROM Employees e
JOIN (
  SELECT dept_id, AVG(salary) AS avg_sal, STDDEV(salary) AS stddev_sal
  FROM Employees GROUP BY dept_id
) d ON e.dept_id = d.dept_id
WHERE ABS(e.salary - d.avg_sal) > 2 * d.stddev_sal;
Output Explanation
Returns employees whose salary deviates from their department's average by more than two standard deviations, flagging potential outliers.
💡 Interview Tip: Bringing in STDDEV() for outlier detection shows statistical fluency beyond basic SQL — a strong differentiator for data analyst roles.

22. Common SQL Interview Mistakes

  • Confusing WHERE and HAVING — WHERE filters rows before grouping; HAVING filters after.
  • Using COUNT(*) when COUNT(column) is needed — leads to incorrect counts with LEFT JOINs.
  • Forgetting the JOIN condition — accidentally creates a CROSS JOIN.
  • Using NOT IN with a nullable subquery — silently returns zero rows.
  • Assuming SQL executes top to bottom — the real logical order is FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY.
  • Overusing SELECT * — hurts performance and readability.
  • Not handling NULLs explicitly — NULL comparisons never evaluate to true.
  • Ignoring indexing on foreign keys — causes slow joins at scale.
⚠️ Interview Warning: Even syntactically correct queries can be marked wrong if you can't explain the execution plan or edge cases (NULLs, duplicates, ties). Always narrate your thought process out loud.

23. SQL Optimization & Performance Tuning Tips

Query Optimization Checklist

  • Select only required columns — avoid SELECT *.
  • Filter early using WHERE before JOINs where possible.
  • Index columns used in JOIN, WHERE, and ORDER BY clauses.
  • Prefer JOINs over correlated subqueries for large datasets.
  • Use EXPLAIN / EXPLAIN PLAN to detect full table scans.
  • Use UNION ALL instead of UNION when duplicates are acceptable.
  • Avoid functions on indexed columns in WHERE (e.g., WHERE YEAR(order_date) = 2025 disables the index — use a date range instead).
  • Batch large INSERT/UPDATE/DELETE operations instead of single massive transactions.

Indexing Interview Questions

What is a Composite Index and does column order matter?

A composite index spans multiple columns. Column order matters greatly — the index is most useful when queries filter on the leading (leftmost) column(s) first, similar to how a phone book is sorted by last name first, then first name.

SQL
CREATE INDEX idx_dept_salary ON Employees(dept_id, salary);
-- Efficiently used by:
SELECT * FROM Employees WHERE dept_id = 3 AND salary > 50000;
-- NOT efficiently used by:
SELECT * FROM Employees WHERE salary > 50000;

Why might an index NOT be used even if it exists?

The optimizer may skip an index if the table is small (full scan is cheaper), if a function/calculation is applied to the indexed column, if there's a leading wildcard in a LIKE pattern (e.g., LIKE '%abc'), or if statistics are outdated.

24. SQL Cheat Sheet

Quick Syntax Cheat Sheet
TaskSyntax
Select columnsSELECT col1, col2 FROM table;
Filter rowsWHERE condition
Sort resultsORDER BY col ASC|DESC
Group rowsGROUP BY col
Filter groupsHAVING condition
Join tablesJOIN table ON condition
Combine result setsUNION / UNION ALL
Rank rowsROW_NUMBER() OVER (...)
Temporary named queryWITH name AS (...)
Save changesCOMMIT;
Undo changesROLLBACK;

25. Quick Revision Notes

  • Execution order: FROM → WHERE → GROUP BY → HAVING → SELECT → ORDER BY → LIMIT.
  • WHERE filters rows; HAVING filters groups.
  • DDL auto-commits; DML can be rolled back.
  • INNER JOIN = matches only; LEFT/RIGHT JOIN = all + matches; FULL OUTER = everything.
  • ROW_NUMBER = unique; RANK = skips ties; DENSE_RANK = no skips.
  • UNION removes duplicates; UNION ALL keeps them (and is faster).
  • ACID = Atomicity, Consistency, Isolation, Durability.
  • Normalize for data integrity; denormalize for read performance.
  • NOT EXISTS is generally safer than NOT IN with nullable columns.

26. SQL Interview Preparation Roadmap

Week 1 — Foundations

  • SELECT, WHERE, ORDER BY, basic operators
  • DDL/DML/DCL/TCL commands
  • Constraints and Keys

Week 2 — Grouping & Joins

  • GROUP BY, HAVING, aggregate functions
  • All JOIN types with practice on Employees/Departments/Orders

Week 3 — Advanced Querying

  • Subqueries and correlated subqueries
  • CTEs and recursive CTEs
  • Window functions (ROW_NUMBER, RANK, LAG/LEAD)

Week 4 — Database Design & Performance

  • Views, indexes, stored procedures, triggers
  • Transactions, ACID, isolation levels
  • Normalization, query optimization, EXPLAIN plans

Week 5 — Mock Practice

  • Solve all 100 questions in this guide without looking at answers first
  • Practice explaining your query logic out loud (interviewers assess communication too)
  • Attempt timed mock interviews or platforms like LeetCode SQL / HackerRank SQL

27. Frequently Asked Questions

SQL is essential but rarely sufficient alone. Most Data Analyst roles in 2026 also expect Excel/Power BI or Tableau for visualization, Python (Pandas/NumPy) for deeper analysis, and strong business communication skills. SQL is typically the single most-tested skill in interviews, but it works best paired with these complementary tools.

With focused daily practice, 4 to 6 weeks is typically enough to go from basics to confidently solving joins, window functions, and scenario-based questions, following a structured roadmap like the one in this article.

JOINs, GROUP BY/HAVING, subqueries, window functions (ROW_NUMBER, RANK, DENSE_RANK, LAG/LEAD), and CTEs are the most frequently tested topics, alongside fundamental concepts like keys, constraints, and normalization.

Core SQL concepts transfer across all databases. PostgreSQL is a strong choice for practice because it closely follows the SQL standard and supports advanced features like window functions and recursive CTEs, but MySQL is equally acceptable for interview preparation.

You should be comfortable writing common patterns (joins, GROUP BY, window functions) from memory, since many interviews involve a whiteboard or shared editor without autocomplete. Understanding the logic matters more than perfect syntax, but fluency builds confidence.

SQL is the standard language used to interact with relational databases. MySQL is a specific database management system that implements SQL, along with its own extensions and dialect-specific features.

Explore more interview-focused guides on AnkitIQCode to round out your Data Analyst and Software Engineering preparation:

28. Conclusion

SQL remains one of the most in-demand, durable technical skills in tech — powering everything from startup MVPs to enterprise data warehouses. Mastering the concepts in this guide, from basic SELECT statements to window functions and query optimization, will put you well ahead of most candidates in your 2026 interviews.

The key isn't memorizing 100 answers word-for-word — it's understanding why each query works, practicing on real tables like Employees, Orders, and Customers, and being able to explain your reasoning clearly under interview pressure. Revisit the cheat sheet and revision notes above the night before your interview, and work through the roadmap consistently in the weeks leading up to it.

Comments are coming soon. In the meantime, share your questions or feedback with Ankit Verma on GitHub, LinkedIn, or YouTube.