Window functions perform calculations across rows related to the current row without collapsing them like
GROUP BY does.1๏ธโฃ ROW_NUMBER()
Gives a unique number to each row in a partition.
SELECT name, dept_id,
ROW_NUMBER() OVER (
PARTITION BY dept_id
ORDER BY salary DESC
) AS rank
FROM employees;
๐ Use case: Rank employees by salary within each department.
2๏ธโฃ RANK() vs DENSE_RANK()
โฆ
RANK() โ Skips numbers on ties (1, 2, 2, 4)โฆ
DENSE_RANK() โ No gaps (1, 2, 2, 3)SELECT name, salary,
RANK() OVER (ORDER BY salary DESC) AS rnk,
DENSE_RANK() OVER (ORDER BY salary DESC) AS dense_rnk
FROM employees;
3๏ธโฃ LAG() and LEAD()
Access previous/next row values.
SELECT name, salary,
LAG(salary) OVER (ORDER BY id) AS prev_salary,
LEAD(salary) OVER (ORDER BY id) AS next_salary
FROM employees;
๐ Use case: Compare current row to previous/next (e.g., salary or stock change).
4๏ธโฃ NTILE(n)
Divides rows into
n buckets.SELECT name,
NTILE(4) OVER (ORDER BY salary DESC) AS quartile
FROM employees;
๐ Use case: Quartiles/percentile-style grouping.
5๏ธโฃ SUM(), AVG(), COUNT() with OVER()
Running totals, partition-wise aggregates, moving stats.
SELECT name, dept_id, salary,
SUM(salary) OVER (PARTITION BY dept_id) AS dept_total
FROM employees;
๐ง Interview Q&A
Q1: Difference between GROUP BY and OVER()?
โฆ
GROUP BY โ Collapses rows into groups; one row per group.โฆ
OVER() โ Keeps all rows; adds an extra column with the aggregate.Q2: When would you use LAG()?
To compare current row values with previous ones (e.g., dayโtoโday revenue change, previous monthโs balance).
Q3: What happens if no PARTITION BY is used?
The function runs over the entire result set as a single partition.
Q4: Can you sort inside OVER()?
Yes,
ORDER BY inside OVER() defines the calculation order (needed for ranking, LAG/LEAD, running totals).๐ฌ Double Tap โค๏ธ for more!