Window Functions

Perform calculations across rows related to the current row

#window #over #partition #rank #row_number

Window Functions

Window functions perform calculations across a set of rows related to the current row.

ROW_NUMBER()

-- Assign sequential numbers to rows
SELECT
  product_id,
  name,
  price,
  ROW_NUMBER() OVER (ORDER BY price DESC) as row_num
FROM products;

RANK() and DENSE_RANK()

-- Rank products by price (with gaps vs without gaps)
SELECT
  product_id,
  name,
  price,
  RANK() OVER (ORDER BY price DESC) as rank,
  DENSE_RANK() OVER (ORDER BY price DESC) as dense_rank
FROM products;

PARTITION BY

-- Row number within each category
SELECT
  product_id,
  name,
  category,
  price,
  ROW_NUMBER() OVER (
    PARTITION BY category
    ORDER BY price DESC
  ) as rank_in_category
FROM products;

Running Total (SUM with Window)

-- Calculate running total of order values
SELECT
  order_id,
  order_date,
  total,
  SUM(total) OVER (
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
  ) as running_total
FROM orders;

Moving Average

-- Calculate 3-day moving average
SELECT
  order_date,
  total,
  AVG(total) OVER (
    ORDER BY order_date
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  ) as moving_avg_3day
FROM orders;

LAG() and LEAD()

-- Compare current row with previous and next
SELECT
  product_id,
  name,
  price,
  LAG(price, 1) OVER (ORDER BY price) as prev_price,
  LEAD(price, 1) OVER (ORDER BY price) as next_price,
  price - LAG(price, 1) OVER (ORDER BY price) as price_diff
FROM products;

FIRST_VALUE() and LAST_VALUE()

-- Get first and last values in window
SELECT
  order_id,
  user_id,
  order_date,
  total,
  FIRST_VALUE(total) OVER (
    PARTITION BY user_id
    ORDER BY order_date
  ) as first_order_total,
  LAST_VALUE(total) OVER (
    PARTITION BY user_id
    ORDER BY order_date
    ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
  ) as last_order_total
FROM orders;

NTILE()

-- Divide rows into N equal groups (quartiles)
SELECT
  product_id,
  name,
  price,
  NTILE(4) OVER (ORDER BY price) as price_quartile
FROM products;

Cumulative Distribution (CUME_DIST)

-- Calculate cumulative distribution
SELECT
  product_id,
  name,
  price,
  CUME_DIST() OVER (ORDER BY price) as cumulative_dist,
  PERCENT_RANK() OVER (ORDER BY price) as percent_rank
FROM products;

Complex Window with Multiple Partitions

-- Analyze sales performance by category and month
SELECT
  category,
  DATE_TRUNC('month', order_date) as month,
  SUM(total) as monthly_sales,
  AVG(SUM(total)) OVER (
    PARTITION BY category
    ORDER BY DATE_TRUNC('month', order_date)
    ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
  ) as moving_avg_sales,
  RANK() OVER (
    PARTITION BY DATE_TRUNC('month', order_date)
    ORDER BY SUM(total) DESC
  ) as category_rank
FROM orders o
JOIN products p ON o.product_id = p.product_id
GROUP BY category, DATE_TRUNC('month', order_date);

Top N per Group

-- Get top 3 products per category
SELECT *
FROM (
  SELECT
    product_id,
    name,
    category,
    price,
    ROW_NUMBER() OVER (
      PARTITION BY category
      ORDER BY price DESC
    ) as rn
  FROM products
) ranked
WHERE rn <= 3;

Discover another handy tool from EditPDF.pro