🔔 Prelude:

Boss: “I need the average sales for 7 days.”

Me: “Sure! Which 7 days?”

Boss: “All the 7 days!”

Me: “Su…Sure…?”

🖋️ Window Functions

Window functions are generally applied after aggregate functions like MAX(), MIN(), AVG() to perform calculations across a set of table rows(days before, days after) that are related to the current row(current day).

Example Table 1: employees

employee_iddepartment_idsalary
11015000
21016000
31015500
41027000
51027200
61026800

Example 1: OVER() Without Partitioning

Calculate the average salary for all employees:

SELECT
    employee_id,
    department_id,
    salary,
    AVG(salary) OVER() AS avg_salary_all_departments
FROM
    employees;

Result:

employee_iddepartment_idsalaryavg_salary_all_departments
110150006250
210160006250
310155006250
410270006250
510272006250
610268006250

Example 2: PARTITION BY

Calculate the average salary per department:

SELECT
    employee_id,
    department_id,
    salary,
    AVG(salary) OVER(PARTITION BY department_id) AS avg_salary_per_department
FROM
    employees;

Result:

employee_iddepartment_idsalaryavg_salary_per_department
110150005500
210160005500
310155005500
410270007000
510272007000
610268007000

Example 3: ORDER BY with Ranking

Rank employees by salary within their departments:

SELECT
    employee_id,
    department_id,
    salary,
    RANK() OVER(PARTITION BY **department_id** ORDER BY **salary** DESC) AS **salary_rank**
FROM
    employees;

Result:

employee_iddepartment_idsalarysalary_rank
210160001
310155002
110150003
510272001
410270002
610268003

Example Table 2: orders

order_idorder_dateorder_total
12023-01-01100
22023-01-03200
32023-01-05150
42023-01-07250
52023-01-09300

Example 4: RANGE with Date Intervals

Sum the total orders in the last 7 days for each row: (INTERVAL 6 because included CURRENT ROW)

SELECT
    order_id,
    order_date,
    order_total,
    SUM(order_total) OVER(ORDER BY order_date RANGE BETWEEN INTERVAL '6' DAY PRECEDING AND CURRENT ROW) AS sum_last_7_days
FROM
    orders;

Result:

order_idorder_dateorder_totalsum_last_7_days
12023-01-01100100
22023-01-03200300
32023-01-05150450
42023-01-07250700
52023-01-09300950

Example 5: ROWS Between Preceding and Following

Calculate the sum of order totals for the current row and the 2 preceding rows:

SELECT
    order_id,
    order_date,
    order_total,
    SUM(order_total) OVER(ORDER BY order_date ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) AS sum_last_3_orders
FROM
    orders;

Result:

order_idorder_dateorder_totalsum_last_3_orders
12023-01-01100100
22023-01-03200300
32023-01-05150450
42023-01-07250600
52023-01-09300700

References sheet

After max()…

  • OVER(…): Applied over
  • PARTITION BY: Used to divide by
  • ORDER BY [DESC]
  • ROWS [BETWEEN...AND]
    1. n PRECEDING
    2. n FOLLOWING
    3. CURRENT ROW
    4. UNBOUNDED PRECEDING All before
    5. UNBOUNDED FOLLOWING All after
  • RANGE [BETWEEN...AND]
    1. INTERVAL 'n' DAY