SQL Interview Questions
What is the difference between INNER JOIN, LEFT JOIN, RIGHT JOIN, and FULL OUTER JOIN? Explain with examples.
Table: Employees
EmpID EmpName DeptID
1 Alice 10
2 Bob 20
3 Charlie NULL
4 David 30
Table: Departments
DeptID DeptName
10 HR
20 IT
40 Finance
1. INNER JOIN
-------------
Returns only the matching rows from both tables.
Non-matching rows are excluded.
EX: SELECT e.EmpName, d.DeptName FROM Employees e
INNER JOIN Departments d ON e.DeptID = d.DeptID;
Result:
EmpName DeptName
Alice HR
Bob IT
2. LEFT JOIN (LEFT OUTER JOIN)
-----------------------------
Returns all rows from the left table (Employees), and matching rows from the right table (Departments).
If no match, right side columns are NULL.
SELECT e.EmpName, d.DeptName FROM Employees e
LEFT JOIN Departments d ON e.DeptID = d.DeptID;
Result:
EmpName DeptName
Alice HR
Bob IT
Charlie NULL
David NULL
3. RIGHT JOIN (RIGHT OUTER JOIN)
-------------------------------
Returns all rows from the right table (Departments), and matching rows from the left table (Employees).
If no match, left side columns are NULL.
SELECT e.EmpName, d.DeptName FROM Employees e
RIGHT JOIN Departments d ON e.DeptID = d.DeptID;
Result:
EmpName DeptName
Alice HR
Bob IT
NULL Finance
4. FULL OUTER JOIN
-----------------
Returns all rows from both tables, matching where possible.
If no match, missing side will have NULL.
SELECT e.EmpName, d.DeptName FROM Employees e
FULL OUTER JOIN Departments d ON e.DeptID = d.DeptID;
Result:
EmpName DeptName
Alice HR
Bob IT
Charlie NULL
David NULL
NULL Finance
=================================================
What are the differences between DELETE, TRUNCATE, and DROP?
DELETE:
Deletes specific rows from a table based on a WHERE condition.
Can be rolled back.
Performance Slower (row-by-row operation).
Its support WHERE Clause.
DELETE FROM Employees WHERE EmpID = 101;
TRUNCATE:
Deletes all rows from a table quickly.
Doesn't Rollback data.
Performance Faster than DELETE.
Not support WHERE Clause.
TRUNCATE TABLE Employees;
DROP:
Completely removes the table structure and data.
cannot be rolled back.
Performance Fastest – removes table and data dictionary entry.
Not applicable WHERE Clause.
DROP TABLE Employees;
Use Cases:
DELETE – When you want to remove specific records, e.g., delete inactive users.
TRUNCATE – When you want to clear the table before a fresh import or data load.
DROP – When you no longer need the table (e.g., after a refactoring or cleanup).
=================================================
What is the difference between WHERE and HAVING clause?
The WHERE and HAVING clauses are both used to filter records in SQL, but they
work at different stages of query execution and are used for different types of filtering.
WHERE Clause Example:
Filters rows before grouping or aggregation happens.
SELECT EmpName, Salary FROM Employees
WHERE Salary > 50000;
HAVING Clause Example:
Filters after aggregation is performed.
SELECT DeptID, SUM(Salary) AS TotalSalary
FROM Employees GROUP BY DeptID
HAVING SUM(Salary) > 100000;
Combined Example:
SELECT DeptID, COUNT(*) AS EmpCount, AVG(Salary) AS AvgSal
FROM Employees WHERE Status = 'Active'
GROUP BY DeptID HAVING AVG(Salary) > 60000;
=================================================
Write a query to find the second highest salary from an Employee table?
EX:
SELECT DISTINCT Salary FROM Employee
ORDER BY Salary DESC LIMIT 1 OFFSET 1;
LIMIT 1 OFFSET 1 skips the highest and returns the second highest.
Simple and efficient in MySQL/PostgreSQL.
EX:
SELECT MAX(Salary) AS SecondHighestSalary
FROM Employee
WHERE Salary < (
SELECT MAX(Salary)
FROM Employee);
Finds the max salary less than the highest.
Works in all RDBMS including Oracle and SQL Server.
EX:
SELECT Salary
FROM (
SELECT Salary, ROW_NUMBER() OVER (ORDER BY Salary DESC) AS rn
FROM Employee
) AS Ranked WHERE rn = 2;
Only returns the second row in salary order (even if multiple people tie for first).
====================================================
How do you find duplicate records in a table? How do you delete them?
Assume we have a table called Employee:
EmpID EmpName Email
1 Alice alice@example.com
2 Bob bob@example.com
3 Alice alice@example.com
4 Charlie charlie@email.com
To find duplicates based on EmpName and Email:
SELECT EmpName, Email, COUNT(*) AS count
FROM Employee
GROUP BY EmpName, Email
HAVING COUNT(*) > 1;
Delete Duplicate Records (Keep One)
WITH CTE AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY EmpName, Email ORDER BY EmpID) AS rn
FROM Employee)
DELETE FROM CTE
WHERE rn > 1;
Keeps only the first record (lowest EmpID) per duplicate group.
Works in PostgreSQL, SQL Server, Oracle (12c+), MySQL 8.0+
Using Subquery (Older approach for MySQL < 8.0):
DELETE FROM Employee
WHERE EmpID NOT IN (
SELECT MIN(EmpID)
FROM Employee
GROUP BY EmpName, Email);
Keeps the record with minimum EmpID from each duplicate group.
Not efficient on large tables; be careful with NOT IN and NULLs.
Optional: Preview What You’ll Delete:
SELECT *
FROM (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY EmpName, Email ORDER BY EmpID) AS rn
FROM Employee) AS Temp
WHERE rn > 1;
Always check your delete logic with SELECT first.
====================================================
What is a CTE (Common Table Expression)? How is it different from subqueries?
A CTE (Common Table Expression) is a temporary result set that you can reference
within a SELECT, INSERT, UPDATE, or DELETE query. It's defined using the WITH clause.
Syntax:
WITH CTE_Name AS (
SELECT column1, column2
FROM SomeTable
WHERE condition)
SELECT * FROM CTE_Name
WHERE another_condition;
You can reuse the CTE in the main query.
Acts like a named subquery that improves readability and modularity.
Example:
Suppose you want to get departments where total salary > 1 lakh:
WITH DeptSalary AS (
SELECT DeptID, SUM(Salary) AS TotalSalary
FROM Employee
GROUP BY DeptID)
SELECT DeptID
FROM DeptSalary
WHERE TotalSalary > 100000;
====================================================
What are RANK(), DENSE_RANK() and ROW_NUMBER()? Where have you used them?
1. ROW_NUMBER()
Assigns a unique sequential number to each row within a partition.
No ties — even if rows have the same value, they get different numbers.
SELECT EmpName, Salary,
ROW_NUMBER() OVER (ORDER BY Salary DESC) AS RowNum
FROM Employee;
EmpName Salary RowNum
Bob 85000 1
Alice 85000 2
David 70000 3
Charlie 60000 4
Use case: pagination, or keeping just one row per group.
2. RANK()
Assigns the same rank to tied rows.
Skips ranks after ties (non-continuous).
SELECT EmpName, Salary,
RANK() OVER (ORDER BY Salary DESC) AS SalaryRank
FROM Employee;
EmpName Salary Rank
Bob 85000 1
Alice 85000 1
David 70000 3
Charlie 60000 4
Use case: When you want to rank rows with potential ties.
3. DENSE_RANK()
Like RANK(), but does not skip the next rank after a tie (continuous).
SELECT EmpName, Salary,
DENSE_RANK() OVER (ORDER BY Salary DESC) AS SalaryRank
FROM Employee;
EmpName Salary Rank
Bob 85000 1
Alice 85000 1
David 70000 2
Charlie 60000 3
Use case: When you need dense/compact ranks even with ties.
====================================================
How do you optimize a slow SQL query? What steps do you take?
1. Use Proper Indexing
Index columns used in WHERE, JOIN, ORDER BY, and GROUP BY.
Avoid functions on indexed columns (e.g., WHERE UPPER(name) = ...).
WHERE EmpID = 123 (Good)
WHERE YEAR(created_at) = 2023 (Bad)
2. **Avoid SELECT ***
Always select only the required columns.
SELECT EmpName, Salary FROM Employee; (Good)
SELECT * FROM Employee; (Bad)
3. Use Joins Smartly
Use INNER JOIN instead of LEFT JOIN if nulls are not needed.
Join on indexed columns whenever possible.
4. Filter Early with WHERE
Apply filters before GROUP BY or JOIN to reduce row counts early.
5. Optimize GROUP BY and Aggregates
Group only on necessary columns.
Use HAVING only for aggregate filters, not row-level conditions.
6. Use LIMIT / OFFSET for Pagination
Prevents returning large result sets in APIs.
SELECT EmpName FROM Employee ORDER BY EmpName LIMIT 20 OFFSET 40;
7. Avoid N+1 Queries
In Java (JPA/Hibernate), avoid multiple small queries by using fetch joins or batch fetching.
Tools for Query Optimization:
Tool Usage
EXPLAIN Execution plan
AUTO TRACE (Oracle) Query profiling
pgAdmin (PostgreSQL) Visual plan analysis
SQL Server Profiler SQL Server query performance
Hibernate show_sql,format_sql Debugging JPA queries
==================================================