Your company has an Employees table and a Departments table. Management wants a report showing all employees, even those who are not assigned to any department. Which JOIN would you use and why?
Answer
Imagine you are compiling an organizational directory where the main focus is ensuring not a single person gets left behind. You have an Employees table on the left and a Departments table on the right.
You should use a LEFT JOIN from the Employees table to the Departments table. A LEFT JOIN is loyal to the first table listed. It extracts every single row from the left table regardless of whether it finds a matching department code on the right. When an employee is unassigned, the department columns simply fill with blank NULL values, keeping the employee visible in the final report.
Example:
SELECT e.employee_id, e.name, d.department_name
FROM employees e
LEFT JOIN departments d
ON e.department_id = d.department_id;
Interview Tip: Always position the table containing the master list you want to preserve entirely on the left side of a LEFT JOIN layout.
A query that searches customers by email has become very slow after the table reached 10 million rows. How would you improve its performance?
Answer
Imagine sifting through a stack of ten million unorganized customer files looking for a specific email address. Without a map, you have to read every single page from top to bottom.
To fix this, you need to create a non-clustered index specifically on the email column. This builds a fast, sorted lookup directory that lets the database engine jump straight to the exact record. You also need to verify that your SQL queries are sargable, meaning they do not wrap the email column in functions like LOWER() or UPPER() which break the index search. Finally, run a statistics update command so the database optimizer knows exactly how the data is distributed.
Example:
CREATE UNIQUE INDEX idx_customers_email
ON customers(email);
Interview Tip: An index is useless if your WHERE clause isn't sargable. Avoid patterns like WHERE LOWER(email) = 'user@email.com' and use matching case inputs instead.
A banking application transfers ₹5,000 from Account A to Account B. The amount is deducted from A, but the server crashes before it's added to B. How can SQL ensure data consistency?
Answer
Imagine a cash transaction where money leaves your hand but the recipient drops it down a drain before pocketing it. In banking, this partial success creates a catastrophic imbalance.
SQL solves this by wrapping the entire sequence inside a strict transaction block using BEGIN TRANSACTION and COMMIT. This invokes the Atomicity principle of ACID compliance, treating the separate debit and credit statements as a single, indivisible unit of work. If the server crashes mid-process, the database engine automatically executes a rollback on restart, restoring the deducted cash to Account A as if nothing ever happened.
Example:
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 5000 WHERE account_id = 'A';
UPDATE accounts SET balance = balance + 5000 WHERE account_id = 'B';
COMMIT;
Interview Tip: Mention ACID properties—specifically Atomicity—to show you understand how databases guarantee all-or-nothing execution for critical monetary workflows.
An Orders table stores customer details repeatedly for every order, making updates difficult. How would you redesign the database?
Answer
Imagine a sales ledger where the clerk meticulously writes out a customer's full home address and phone number next to every single item they purchase. If the customer moves, you have to hunt down hundreds of historical rows to change the text.
You need to normalize the database by breaking this flat layout into two separate, dedicated files. Extract all recurring customer details into a new Customers table where each buyer gets a unique Customer ID primary key. Then, strip the messy text columns out of the Orders table, leaving only a lean Customer ID foreign key column that points back to the master profiles.
Example:
The new streamlined orders layout relies on a clean linkage:
ALTER TABLE orders
ADD CONSTRAINT fk_orders_customer
FOREIGN KEY (customer_id) REFERENCES customers(customer_id);
Interview Tip: Relational databases thrive on normalization. Moving from a single repetitive layout to separated tables removes update anomalies and shrinks your disk storage footprints.
Two transactions are waiting for each other to release locks, and neither can continue. What happened, and how would you prevent it?
Answer
Imagine two drivers meeting head-on in a narrow one-lane alleyway. Neither driver can back up because there is a car parked directly behind them, leaving both vehicles completely stuck forever waiting for the other to move.
This gridlock is known as a deadlock. You can prevent this from stalling your applications by forcing all code pathways to request and acquire locks on tables in the exact same logical order. Additionally, keep your transaction scripts incredibly short, avoid letting queries pause for user inputs mid-transaction, and configure a retry logic mechanism in your application layer to catch and resubmit aborted queries.
Interview Tip: Explain that modern database engines automatically detect deadlocks and sacrifice one transaction as the victim to let the other survive, making application-side retry logic essential.
A query becomes slow after the table grows to millions of rows.
Answer
Imagine a system search script that ran smoothly during development but grinds to a halt once real users flood the application with millions of operational records.
Your first step is to generate and analyze the visual execution plan to see exactly where the engine is struggling. Look for heavy table scans and replace them with strategic indexes on your filtered columns. If the table is tracking historical time-series data, implement horizontal partitioning to split the massive file by date ranges. Keep your optimizer sharp by updating table statistics regularly, and refactor any non-sargable wildcards or mathematical operations inside your predicates.
Example:
Run diagnostic plans to spot bottlenecks:
EXPLAIN ANALYZE SELECT * FROM sales WHERE order_date >= '2026-01-01';
Interview Tip: A junior developer just adds an index; an intermediate developer opens the execution plan first to diagnose the true root cause of the slowdown.
Customers report duplicate records appearing in reports.
Answer
Imagine looking at an analytical statement where the exact same transaction appears duplicated across multiple rows, throwing off your overall totals and destroying user trust.
To troubleshoot this, you need to write a diagnostic query that groups the data by the columns that define uniqueness and uses a HAVING COUNT clause to isolate the repeated keys. Once you locate the duplicates, clean up the bad rows using a Common Table Expression paired with a row-number function. Finally, build a permanent defensive wall by adding a UNIQUE constraint to stop duplicates from ever leaking into the schema again.
Example:
Finding the problematic data rows looks like this:
SELECT email, COUNT(*)
FROM users
GROUP BY email
HAVING COUNT(*) > 1;
Interview Tip: Finding duplicates is only half the battle; always emphasize adding a UNIQUE constraint or index as the final architectural cure.
A report should include employees who have no department.
Answer
Imagine an administrative audit where you need to identify temporary contractors, new hires, or unassigned staff members who are not tied to any official corporate department budget.
You can solve this by running a LEFT JOIN from the Employees table to the Departments table, which naturally retains every worker row. To isolate the unassigned individuals, add a WHERE clause filtering for records where the joined department primary key fields turn up completely NULL. This strips away all properly matched staff, leaving only the unassigned workers.
Example:
SELECT e.name, e.employee_id
FROM employees e
LEFT JOIN departments d ON e.department_id = d.department_id
WHERE d.department_id IS NULL;
Interview Tip: When checking for missing relationships after a outer join, always explicitly check for NULL on a column that is defined as NOT NULL in the target table, like its primary key.
A dashboard query takes 30 seconds to load.
Answer
Imagine an executive dashboard that displays a spinning loading wheel for half a minute every time a manager attempts to view daily metrics.
You need to optimize this by inspecting the execution plan to spot missing composite indexes on the filtered dashboard parameters. Stop using SELECT * and modify the query to extract only the specific columns required by the UI grid. For complex aggregations that calculate totals over millions of rows, consider pre-computing the results using a Materialized View with a scheduled refresh pattern, or implement an application-level caching layer like Redis.
Interview Tip: Dashboards require low latency. Transitioning heavy aggregate math out of live queries and into materialized views or summary tables is a standard architectural pattern.
Two users update the same row simultaneously.
Answer
Imagine two travel agents attempting to book the very last seat on a flight for two different clients at the exact same fraction of a second.
You can manage this concurrency conflict using Optimistic Locking by adding a version number or timestamp column to the row. When an update is attempted, the database ensures the version matches the original read value; if it doesn't, the transaction is safely rejected. Alternatively, if updates are constantly colliding, switch to Pessimistic Locking by applying an explicit row-level write lock to isolate the record until the update finishes.
Example:
Optimistic row update verification:
UPDATE flights SET seats = seats - 1, version = version + 1
WHERE flight_id = 101 AND version = 5;
Interview Tip: Use optimistic locking for high-concurrency web apps where conflicts are rare, and save pessimistic locking for critical systems where data clashes are frequent.
A transaction fails halfway through a payment process.
Answer
Imagine an online checkout system that successfully marks an order as paid, but crashes right before it decrements the warehouse stock counter, leading to phantom inventory errors.
To guarantee all-or-nothing reliability, enclose the entire payment sequence inside an explicit transaction block wrapped in a try-catch block. If any single command fails or throws a timeout error, the catch script instantly fires a ROLLBACK command. This unwinds all partial modifications made since the start of the block, returning the entire database schema to a perfectly consistent, pristine state.
Example:
Handling an unexpected failure cleanly:
BEGIN TRY
BEGIN TRANSACTION;
-- Execute payment updates here
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
ROLLBACK TRANSACTION;
END CATCH;
Interview Tip: Always pair your database transaction blocks with proper try-catch error handling routines in your application or stored procedure code.
A database server's CPU usage suddenly spikes.
Answer
Imagine an operational database cluster where the CPU utilization suddenly pegs at one hundred percent, slowing down every connected system and threatening an outage.
You need to immediately check the active process list using diagnostic tools to identify long-running, resource-intensive queries. Look out for unoptimized queries executing massive sorting operations, implicit data type conversions, or giant hash joins caused by missing indexes. If the queries look healthy, investigate whether a heavy automated database backup job, statistics collection run, or index rebuild was accidentally scheduled during peak operational hours.
Interview Tip: Mention specific system view commands like SP_WHO2 in SQL Server or pg_stat_activity in PostgreSQL to demonstrate real-world troubleshooting experience.
An index exists, but SQL still performs a full table scan.
Answer
Imagine printing a comprehensive index at the back of a textbook, but the student still decides to read the entire book from page one to find their answer because the index wasn't built for their specific question.
This happens if your query predicates are non-sargable, such as applying functions directly to the indexed column or using leading wildcards like LIKE '%text%'. The database engine will also bypass an index and perform a full table scan if the index lacks selectivity—meaning the optimizer calculates that it is actually cheaper to read the entire table rather than constantly jumping back and forth between an index structure and data pages.
Example:
Non-sargable pattern that causes table scans:
SELECT * FROM employees WHERE YEAR(hire_date) = 2026;
Sargable fix that utilizes the index:
SELECT * FROM employees WHERE hire_date >= '2026-01-01' AND hire_date <= '2026-12-31';
Interview Tip: An index is merely a tool; the query must be written correctly to enable the engine's query optimizer to actually utilize it.
You need to archive old data without affecting current queries.
Answer
Imagine a historical warehouse ledger that grows so thick and heavy that clerks struggle to look up fresh orders because they have to lift years of outdated records out of the way.
The cleanest strategy is to implement an automated date-based partitioning scheme. This physically separates your records into independent data segments based on time intervals, allowing live queries to skip old data entirely. Alternatively, set up an automated background archiving job that batch-transfers rows older than a specific retention threshold out of the main operational table and inserts them into an isolated historical archive table.
Interview Tip: Emphasize performing data deletion and movement in small, controlled batches rather than one massive delete statement to prevent transaction log exhaustion and table lockups.
The business wants faster reports but also frequent updates—how would you balance indexing and write performance?
Answer
Imagine a balance scale where adding heavy weights to one side to speed up read reporting automatically slows down your real-time data writes, because every new index requires the database to perform extra work during inserts.
To balance these competing goals, focus on creating highly selective indexes that target your most frequent reporting bottlenecks. Implement covering indexes using INCLUDE clauses to satisfy queries directly from the index tree without touching table pages, and prune away completely unused or duplicate indexes. For heavy real-time data ingestion, route writes into a lean, write-optimized partition, while isolating heavy analytical reporting workflows onto read-only database replicas.
Interview Tip: Explain the read-write trade-off clearly: indexes accelerate SELECT queries but act as a performance tax on INSERT, UPDATE, and DELETE operations.
Premium Content
Unlock Scenario Questions - Part 1 and all premium lessons with a subscription.
All premium lessons
Ad-free experience
Priority support
From ₹199.99/year — See plans