Using Named Windows with WINDOW Clause in PostgreSQL
📖 Scenario: You work in a sales department and want to analyze monthly sales data for different salespeople. You want to calculate running totals and averages over specific time frames without repeating the same window definitions multiple times.
🎯 Goal: Build a SQL query that uses the WINDOW clause to define named windows and then use those named windows in OVER clauses to calculate running totals and averages.
📋 What You'll Learn
Create a table called sales with columns salesperson (text), month (integer), and amount (integer).
Insert the exact sales data for three salespeople over three months.
Define a named window called monthly_window that partitions by salesperson and orders by month.
Use the named window monthly_window to calculate a running total of amount.
Use the named window monthly_window to calculate a running average of amount.
💡 Why This Matters
🌍 Real World
Sales analysts often need to calculate running totals and averages over time for each salesperson to track performance trends.
💼 Career
Knowing how to use named windows in SQL is useful for writing efficient and readable analytical queries in business intelligence and data analysis roles.
Progress0 / 4 steps
1
Create the sales table and insert data
Create a table called sales with columns salesperson (text), month (integer), and amount (integer). Then insert these exact rows: ('Alice', 1, 100), ('Alice', 2, 150), ('Alice', 3, 200), ('Bob', 1, 80), ('Bob', 2, 120), ('Bob', 3, 160), ('Charlie', 1, 90), ('Charlie', 2, 110), ('Charlie', 3, 130).
PostgreSQL
Hint
Use CREATE TABLE to define the table and INSERT INTO with multiple rows to add the data.
2
Define a named window with WINDOW clause
Write a SELECT statement from sales and add a WINDOW clause that defines a named window called monthly_window which partitions by salesperson and orders by month.
PostgreSQL
Hint
Use the WINDOW clause after the FROM clause to define monthly_window.
3
Calculate running total using the named window
Extend the SELECT statement to include a column called running_total that calculates the running total of amount using SUM(amount) OVER monthly_window.
PostgreSQL
Hint
Add SUM(amount) OVER monthly_window AS running_total to the SELECT list.
4
Calculate running average using the named window
Add another column called running_avg that calculates the running average of amount using AVG(amount) OVER monthly_window in the same SELECT statement.
PostgreSQL
Hint
Add AVG(amount) OVER monthly_window AS running_avg to the SELECT list.
Practice
(1/5)
1. What is the main purpose of using the WINDOW clause in PostgreSQL?
easy
A. To join multiple tables using window functions
B. To create temporary tables for complex queries
C. To define named window specifications for reuse in the query
D. To specify the order of rows in a SELECT statement
Solution
Step 1: Understand the role of WINDOW clause
The WINDOW clause allows defining named window specifications once for reuse.
Step 2: Compare options with WINDOW clause purpose
Options A, B, and C describe other SQL features, not the WINDOW clause.
Final Answer:
To define named window specifications for reuse in the query -> Option C
2. Which of the following is the correct syntax to define a named window called w1 that orders rows by date ascending?
easy
A. WINDOW w1 (ORDER BY date ASC)
B. WINDOW w1 AS (ORDER BY date ASC)
C. WINDOW w1 BY (ORDER date ASC)
D. WINDOW AS w1 ORDER BY date ASC
Solution
Step 1: Recall WINDOW clause syntax
The correct syntax is WINDOW name AS (window_definition), e.g., WINDOW w1 AS (ORDER BY date ASC).
Step 2: Check each option's syntax
WINDOW w1 AS (ORDER BY date ASC) matches correct syntax. Options A, B, and D have incorrect keyword order or missing AS.
Final Answer:
WINDOW w1 AS (ORDER BY date ASC) -> Option B
Quick Check:
WINDOW name AS (definition) syntax [OK]
Hint: Use WINDOW name AS (definition) syntax [OK]
Common Mistakes:
Omitting AS keyword
Using BY instead of ORDER BY
Misplacing parentheses
3. Given the query:
SELECT department, employee, salary, AVG(salary) OVER w AS avg_salary
FROM employees
WINDOW w AS (PARTITION BY department ORDER BY employee)
ORDER BY department, employee;
What does the avg_salary column show?
medium
A. The average salary of employees in the same department up to the current employee
B. The average salary of all employees in the company
C. The average salary of employees partitioned by department without order
D. The average salary of employees ordered by employee name across all departments
Solution
Step 1: Analyze the WINDOW clause
The window named w partitions rows by department and orders by employee.
Step 2: Understand AVG() OVER w behavior
AVG(salary) OVER w calculates the average salary for rows in the same department up to the current employee in order.
Final Answer:
The average salary of employees in the same department up to the current employee -> Option A
Quick Check:
Partition + order = running average per department [OK]
Hint: Partition + order means running calculation per group [OK]
Common Mistakes:
Ignoring ORDER BY in window
Assuming average over entire table
Confusing partition with no partition
4. Consider this query:
SELECT name, salary, SUM(salary) OVER w
FROM employees
WINDOW w AS (PARTITION BY department ORDER BY name BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW);
It returns an error. What is the likely cause?
medium
A. The window frame clause requires ROWS or RANGE keyword explicitly
B. The window frame clause is invalid without RANGE keyword
C. The WINDOW clause must come after ORDER BY clause
D. The window name cannot be used in the OVER clause
Solution
Step 1: Check window frame syntax
The frame clause must specify ROWS or RANGE explicitly before frame boundaries.
Step 2: Identify error cause
The query has ORDER BY name BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW, missing the required ROWS or RANGE keyword before BETWEEN.
Final Answer:
The window frame clause requires ROWS or RANGE keyword explicitly -> Option A
Quick Check:
Window frame needs ROWS or RANGE keyword [OK]
Hint: Always specify ROWS or RANGE in window frame [OK]
Common Mistakes:
Placing WINDOW clause after ORDER BY
Omitting ROWS or RANGE keyword
Using window name incorrectly in OVER
5. You want to calculate the cumulative sum of sales per region ordered by date, and reuse this window in multiple queries. Which is the best way to define and use a named window for this purpose?
hard
A. Define WINDOW sales_win AS (PARTITION BY region ORDER BY date ROWS UNBOUNDED PRECEDING) and use SUM(sales) OVER sales_win
B. Use SUM(sales) OVER (PARTITION BY region ORDER BY date) without WINDOW clause
C. Define WINDOW sales_win AS (ORDER BY date PARTITION BY region) and use SUM(sales) OVER sales_win
D. Define WINDOW sales_win AS (PARTITION BY region ORDER BY date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) and use SUM(sales) OVER sales_win
Solution
Step 1: Understand cumulative sum window frame
Cumulative sum requires a frame from the start to current row, so use RANGE or ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
Step 2: Check window definition correctness
Define WINDOW sales_win AS (PARTITION BY region ORDER BY date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) and use SUM(sales) OVER sales_win correctly defines WINDOW with PARTITION BY region, ORDER BY date, and RANGE frame for cumulative sum.
Step 3: Compare with other options
Define WINDOW sales_win AS (PARTITION BY region ORDER BY date ROWS UNBOUNDED PRECEDING) and use SUM(sales) OVER sales_win uses ROWS UNBOUNDED PRECEDING which sums the entire partition, not cumulatively. Define WINDOW sales_win AS (ORDER BY date PARTITION BY region) and use SUM(sales) OVER sales_win has wrong order of clauses. Use SUM(sales) OVER (PARTITION BY region ORDER BY date) without WINDOW clause does not reuse named window.
Final Answer:
Define WINDOW sales_win AS (PARTITION BY region ORDER BY date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) and use SUM(sales) OVER sales_win -> Option D
Quick Check:
Named window with correct frame = Define WINDOW sales_win AS (PARTITION BY region ORDER BY date RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) and use SUM(sales) OVER sales_win [OK]
Hint: Use RANGE UNBOUNDED PRECEDING for cumulative sums [OK]
Common Mistakes:
Omitting frame clause for cumulative sum
Incorrect order of PARTITION BY and ORDER BY
Not using named window for reuse
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.