The questions that come up most often, each with a sample answer you can adapt into your own words. Read them out loud until the explanation feels natural.
What is the difference between an INNER JOIN and a LEFT JOIN?
FundamentalsAn INNER JOIN returns only rows that match in both tables. A LEFT JOIN returns every row from the left table and the matching rows from the right, filling NULLs where there is no match. Use a LEFT JOIN when you need to keep all left-side rows regardless of whether a related right-side row exists, for example all customers including those with no orders.
What is the difference between WHERE and HAVING?
IntermediateWHERE filters individual rows before grouping and cannot reference aggregate functions. HAVING filters groups after GROUP BY and can use aggregates like COUNT or SUM. So you use WHERE to restrict which rows enter the aggregation and HAVING to restrict which aggregated groups appear in the result.
What is a window function and when would you use one?
AdvancedA window function computes a value across a set of rows related to the current row without collapsing them into one, using the OVER clause. Examples are ROW_NUMBER() for ranking within a partition, LAG/LEAD to access previous or next rows, and SUM(...) OVER (...) for running totals. Use one whenever you need per-row analytics like 'each employee's salary rank within their department' that a GROUP BY would flatten away.
How would you find the second-highest salary?
IntermediateThe cleanest modern approach uses a window function: SELECT salary FROM (SELECT salary, DENSE_RANK() OVER (ORDER BY salary DESC) AS rnk FROM employees) t WHERE rnk = 2. DENSE_RANK handles ties correctly. A classic alternative is a correlated subquery or SELECT MAX(salary) FROM employees WHERE salary < (SELECT MAX(salary) FROM employees), though that does not generalise to the Nth value as cleanly.
What is an index and what is the tradeoff?
AdvancedAn index is an auxiliary data structure (usually a B-tree) that lets the engine find rows by a column's value without scanning the whole table, turning a lookup from O(n) into roughly O(log n). The tradeoff is that indexes consume storage and slow down writes, because every INSERT, UPDATE, and DELETE must also maintain the index. So you index columns used in WHERE, JOIN, and ORDER BY, but do not index everything.
What is the difference between DELETE, TRUNCATE, and DROP?
IntermediateDELETE removes rows (optionally filtered by WHERE), is logged row by row, and can be rolled back. TRUNCATE removes all rows quickly by deallocating pages, is minimally logged, resets identity counters, and cannot be filtered. DROP removes the entire table including its structure. In short: DELETE for selective removal, TRUNCATE to empty a table fast, DROP to delete the table itself.
What does a primary key guarantee versus a unique constraint?
FundamentalsBoth enforce uniqueness, but a primary key additionally disallows NULLs and there can be only one per table; it is the canonical row identifier and typically the clustered index. A unique constraint enforces uniqueness on a column or set of columns, permits one NULL (in most databases), and you can have several per table. Use the primary key for the row's identity and unique constraints for other naturally unique columns like email.
How do you read an execution plan to optimise a slow query?
AdvancedRun EXPLAIN (or EXPLAIN ANALYZE) and look for the expensive operations: a full table scan or sequential scan on a large table usually means a missing index on the filtered or joined column. Check the join order and method (hash vs nested loop) and the estimated vs actual rows, since a big mismatch points to stale statistics. The common fixes are adding or adjusting an index, rewriting to avoid functions on indexed columns, and updating table statistics.