What are window functions?
Functions that perform calculations across sets of rows related to the current row without collapsing them.
What does ROW_NUMBER() do?
Assigns a unique sequential integer to rows within a partition.
What does RANK() do?
Gives ranks with gaps for ties in ordered results.
What does DENSE_RANK() do?
Gives ranks without gaps for ties.
What clause defines partitions for window functions?
PARTITION BY inside the OVER() clause.
What clause defines order for window functions?
ORDER BY inside the OVER() clause.
What is the difference between GROUP BY and window functions?
GROUP BY collapses rows into one per group, window functions keep individual rows while computing aggregates.
What is a common table expression (CTE)?
A temporary result set defined using WITH that can be referenced within the main query.
What is the difference between a CTE and a subquery?
CTEs can be referenced multiple times and improve readability; subqueries cannot.
How do you calculate cumulative sums using window functions?
SUM(column) OVER(ORDER BY column) computes cumulative totals across rows.
How do you find the previous row’s value in a window?
Use LAG(column) OVER(ORDER BY column) to access the previous row value.
How do you find the next row’s value in a window?
Use LEAD(column) OVER(ORDER BY column) to access the next row value.
How do you select the top N rows per group?
Use ROW_NUMBER() or RANK() with PARTITION BY to rank rows, then filter on the rank.
How do you calculate percentiles or top X% per group?
Use NTILE(n) OVER(PARTITION BY group_column ORDER BY value_column) to divide rows into n buckets.
How can you combine multiple CTEs?
Chain them using WITH cte1 AS (…), cte2 AS (…) SELECT … FROM cte2 JOIN cte1 …
How do you filter aggregated groups using window functions?
Window functions don’t filter rows directly; use ROW_NUMBER()/RANK in a subquery or CTE and then filter in the outer query.
How do you calculate running averages per user?
Use AVG(column) OVER(PARTITION BY user_id ORDER BY date ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW).
How do you find gaps or sequences in data?
Use LAG() or LEAD() to compare current row with previous/next rows, then filter differences.
How do you handle ties in ranking?
RANK() leaves gaps, DENSE_RANK() does not; choose based on requirement.
How do you calculate cumulative counts per group?
COUNT(*) OVER(PARTITION BY group_column ORDER BY sort_column ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW).
How do you write a recursive CTE?
WITH RECURSIVE cte_name AS (anchor_query UNION ALL recursive_query) SELECT * FROM cte_name;
How do you calculate a moving average over last N rows?
AVG(column) OVER(ORDER BY date ROWS BETWEEN N PRECEDING AND CURRENT ROW);
How do you join multiple CTEs?
Define them in WITH clause separated by commas, then reference them in the main SELECT with JOINs.