Window Functions with RANK and LAG
Use window functions to rank rows, calculate running totals, and compare with previous rows without self-joins.
-- Rank users by total spend within each region
SELECT
user_id,
region,
total_spend,
RANK() OVER (PARTITION BY region ORDER BY total_spend DESC) AS rank,
DENSE_RANK() OVER (PARTITION BY region ORDER BY total_spend DESC) AS dense_rank
FROM user_stats;
-- Running total of daily revenue
SELECT
date,
revenue,
SUM(revenue) OVER (ORDER BY date ROWS UNBOUNDED PRECEDING) AS running_total,
AVG(revenue) OVER (ORDER BY date ROWS BETWEEN 6 PRECEDING AND CURRENT ROW) AS avg_7day
FROM daily_revenue;
-- Compare each row with previous (month-over-month)
SELECT
month,
revenue,
LAG(revenue) OVER (ORDER BY month) AS prev_month,
revenue - LAG(revenue) OVER (ORDER BY month) AS change,
ROUND(
(revenue - LAG(revenue) OVER (ORDER BY month))::numeric /
NULLIF(LAG(revenue) OVER (ORDER BY month), 0) * 100, 1
) AS pct_change
FROM monthly_revenue;
-- Top 3 products per category
SELECT * FROM (
SELECT
product_id, category, sales,
ROW_NUMBER() OVER (PARTITION BY category ORDER BY sales DESC) AS rn
FROM products
) ranked
WHERE rn <= 3;Use Cases
- Business reporting
- Leaderboards
- Time-series analysis
Tags
Related Snippets
Similar patterns you can reuse in the same workflow.
SQL Window Functions for Analytics
Advanced SQL window functions for running totals, rankings, moving averages, and gap analysis.
Keyset Pagination vs Offset
Efficient keyset (cursor) pagination pattern compared to traditional OFFSET for large datasets in PostgreSQL.
UPSERT with ON CONFLICT
Insert or update rows atomically using PostgreSQL ON CONFLICT clause with partial indexes and conditions.
Full-Text Search with Ranking
PostgreSQL full-text search using tsvector, tsquery, and ts_rank with trigram similarity for fuzzy matching.