Priya needs to rank salespersons by revenue within each region — and show each person's revenue compared to the previous month. GROUP BY collapses the data into one row per group. She needs all rows intact, with the calculation alongside. That is exactly what window functions do.
What makes window functions different
Aggregate functions (SUM, COUNT, AVG) collapse multiple rows into one. Window functions perform calculations across a set of rows but return one result per row — the data is never collapsed. You keep all your detail and get the summary alongside it.
The OVER clause
Every window function uses the OVER clause to define its "window" — the set of rows it looks at for each calculation. An empty OVER() means the entire result set. PARTITION BY divides rows into groups. ORDER BY within OVER defines the order for ranking and cumulative calculations.
SUM(Revenue) OVER(PARTITION BY Region) -- total per region
SUM(Revenue) OVER(ORDER BY OrderDate) -- running total
ROW_NUMBER and RANK
Salesperson,
Revenue,
ROW_NUMBER() OVER(ORDER BY Revenue DESC) AS RowNum,
RANK() OVER(ORDER BY Revenue DESC) AS Rank_
FROM SalesFact;
Running totals with SUM OVER
OrderDate,
Revenue,
SUM(Revenue) OVER(ORDER BY OrderDate) AS RunningTotal
FROM SalesFact
ORDER BY OrderDate;
LAG and LEAD for period comparison
LAG looks at the previous row's value. LEAD looks at the next row's value. This is how you build month-over-month or year-over-year comparisons without self-joins.
OrderDate,
Revenue,
LAG(Revenue) OVER(ORDER BY OrderDate) AS PrevRevenue,
Revenue - LAG(Revenue) OVER(ORDER BY OrderDate) AS Change_
FROM SalesFact;
COALESCE(LAG(Revenue) OVER(...), 0) to treat the first row's "previous" as zero.Write a query that ranks salespersons by total revenue within each region (use PARTITION BY Region), showing their rank, name, and total revenue. Then find who is ranked #1 in each region.