Advanced SQL — Window Functions, CTEs & Query Optimisation
RANK vs DENSE_RANK vs ROW_NUMBER, LAG/LEAD, running totals, CTEs and recursive queries, subquery vs CTE comparison, EXPLAIN / query plans, indexing strategy, and 8 interview questions with answers — all with Indian business SQL examples.
Window Functions — The Single Biggest SQL Skill Upgrade
A window function performs a calculation across a set of rows related to the current row — unlike GROUP BY which collapses rows into one. The OVER() clause defines the window. Window functions are tested in virtually every senior data analyst interview in India.
CTEs — Write SQL That Reads Like English
A CTE (Common Table Expression) defined with WITH name AS (...) is a named temporary result set. Chain multiple CTEs to build complex analyses step by step, with each step clearly named.
Query Optimisation — Making Slow Queries Fast
Advanced SQL Interview Cheat Sheet
Frequently Asked Questions
What is the difference between RANK, DENSE_RANK, and ROW_NUMBER in SQL?
All three are window functions that assign a sequential number to rows based on an ORDER BY clause, but they handle ties differently. ROW_NUMBER assigns a unique number to every row — no two rows get the same number, even if they have equal values. Ties are broken arbitrarily (by internal row order). RANK assigns the same rank to tied rows, then skips numbers — if two rows tie for rank 1, the next row is rank 3 (not 2). DENSE_RANK also assigns the same rank to ties, but does NOT skip — if two rows tie for rank 1, the next rank is 2. Example: Sales [500, 500, 300]. ROW_NUMBER gives [1, 2, 3]. RANK gives [1, 1, 3]. DENSE_RANK gives [1, 1, 2]. Use ROW_NUMBER when you need exactly one row per group (top-1 per category). Use RANK when you want to identify all entries that tied for a position (top-3 sellers might have 4 entries if two tied for 3rd). Use DENSE_RANK when you want contiguous rank numbers without gaps.
When should you use a CTE instead of a subquery?
Use a CTE (WITH clause) when: the logic is complex enough that it benefits from naming and explaining; the same intermediate result is used more than once in the query; you want to structure multi-step analysis as readable named steps; or you are building a recursive query (only possible with CTEs). Use a subquery when: the logic is short and self-explanatory; it is used in only one place; you need it inline in a WHERE or FROM clause for a quick filter. The practical rule: if a reader would have to re-read the subquery multiple times to understand what it produces, wrap it in a CTE and give it a clear name. Both produce identical query plans in most databases (PostgreSQL, BigQuery, Snowflake, Redshift) — performance difference is negligible unless the CTE is materialised. CTEs substantially improve readability and are preferred in code reviews at data-driven Indian companies.
How do you optimise a slow SQL query in MySQL or PostgreSQL?
A systematic optimisation process: (1) Run EXPLAIN (MySQL) or EXPLAIN ANALYZE (PostgreSQL) to see the query plan — look for full table scans (type: ALL in MySQL; Seq Scan in PostgreSQL) on large tables. (2) Check if columns in WHERE, JOIN ON, and ORDER BY have indexes. Create missing indexes with CREATE INDEX — especially on foreign keys, date columns, and high-cardinality filter columns. (3) Avoid functions on indexed columns in WHERE clauses — WHERE YEAR(order_date) = 2026 cannot use a date index; WHERE order_date BETWEEN '2026-01-01' AND '2026-12-31' can. (4) Avoid SELECT * — retrieve only the columns you need. (5) Filter early — apply WHERE conditions before JOINs when possible, using CTEs or subqueries to reduce row counts. (6) Avoid correlated subqueries that run once per row — replace with a JOIN or window function. (7) On analytical databases (BigQuery, Redshift), partition tables by date and cluster/sort by frequently-filtered columns.
What advanced SQL questions come up in Indian data analyst interviews?
The most common advanced SQL interview questions in India (2026): (1) Write a query to find the second-highest salary — tests knowledge of DENSE_RANK or OFFSET-FETCH. (2) Find the Nth order per customer — tests ROW_NUMBER with PARTITION BY. (3) Calculate a 7-day rolling average of daily revenue — tests AVG() OVER with ROWS BETWEEN. (4) Find customers whose orders increased month-over-month — tests LAG() or self-join approach. (5) Identify products that appear in every category — tests GROUP BY with HAVING COUNT(DISTINCT category) = total. (6) Write a query to de-duplicate keeping the latest record — tests ROW_NUMBER with PARTITION BY id ORDER BY updated_at DESC and an outer WHERE rn = 1. (7) Explain the difference between INNER JOIN and LEFT JOIN with a scenario — tests conceptual clarity. (8) What does EXPLAIN tell you and how do you use it? — tests performance thinking. Practise these on real tables (orders, customers, products) with Indian-context data.
EVIKA ACADEMY · NOIDA SECTOR 51
Master Advanced SQL for Data Analyst Interviews
Our SQL curriculum covers window functions, CTEs, query optimisation, and 100+ practice problems on real Indian business datasets — with mock interview sessions.
Book Free Demo Class →