SUM, AVG, COUNT as window functions in PostgreSQL - Time & Space Complexity
We want to understand how the time to run window functions like SUM, AVG, and COUNT changes as the data grows.
How does the work needed grow when we have more rows in the table?
Analyze the time complexity of the following code snippet.
SELECT employee_id, department_id, salary,
SUM(salary) OVER (PARTITION BY department_id) AS dept_total_salary,
AVG(salary) OVER (PARTITION BY department_id) AS dept_avg_salary,
COUNT(*) OVER (PARTITION BY department_id) AS dept_employee_count
FROM employees;
This query calculates the total, average, and count of salaries for each department using window functions.
Identify the loops, recursion, array traversals that repeat.
- Primary operation: The database scans all rows once and computes aggregates per partition (department).
- How many times: Each row is processed once, but the window function groups rows by department and calculates aggregates over those groups.
As the number of rows grows, the database does more work to group and aggregate salaries per department.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 10 operations to scan and aggregate |
| 100 | About 100 operations, grouping by department |
| 1000 | About 1000 operations, still grouping by department |
Pattern observation: The work grows roughly in direct proportion to the number of rows.
Time Complexity: O(n)
This means the time to run these window functions grows linearly with the number of rows.
[X] Wrong: "Window functions like SUM or AVG run a separate calculation for each row, so time grows much faster than the number of rows."
[OK] Correct: The database optimizes by grouping rows and calculating aggregates efficiently, so it does not repeat full calculations for each row.
Understanding how window functions scale helps you explain query performance clearly and shows you know how databases handle grouped calculations efficiently.
"What if we removed the PARTITION BY clause? How would the time complexity change?"
Practice
COUNT(*) OVER() window function do in PostgreSQL?Solution
Step 1: Understand COUNT(*) OVER() usage
The function counts all rows in the query result but does not group or collapse rows.Step 2: Difference from GROUP BY
Unlike GROUP BY, it keeps all rows visible and adds the count as a column.Final Answer:
Counts all rows in the result set without grouping them. -> Option AQuick Check:
COUNT(*) OVER() counts all rows [OK]
- Confusing window COUNT with GROUP BY count
- Thinking it returns a single aggregated row
- Assuming it counts distinct values only
Solution
Step 1: Identify correct window function syntax
SUM(sales) OVER (ORDER BY date) calculates cumulative sum ordered by date.Step 2: Check other options for syntax errors
The other options misuse window function syntax or omit OVER keyword.Final Answer:
SELECT sales, SUM(sales) OVER (ORDER BY date) AS running_total FROM sales_data; -> Option AQuick Check:
SUM() OVER (ORDER BY ...) is correct syntax [OK]
- Omitting OVER() clause
- Using PARTITION BY without OVER()
- Confusing GROUP BY with window functions
employees with columns department and salary, what will the following query return?SELECT department, salary, AVG(salary) OVER (PARTITION BY department) AS avg_dept_salary FROM employees;
Solution
Step 1: Understand PARTITION BY in AVG window function
AVG(salary) OVER (PARTITION BY department) calculates average salary per department for each row.Step 2: Confirm output per row
Each row keeps salary and adds average salary of that row's department without grouping rows.Final Answer:
Each row shows salary and average salary of its department. -> Option DQuick Check:
AVG() OVER (PARTITION BY ...) averages per group per row [OK]
- Thinking it aggregates to one row per group
- Confusing window AVG with GROUP BY AVG
- Expecting overall average without PARTITION BY
SELECT employee_id, salary, COUNT(*) OVER PARTITION BY department FROM employees;
Solution
Step 1: Check syntax of window function
OVER clause must have parentheses: OVER (PARTITION BY department).Step 2: Validate other parts
COUNT(*) is valid as window function; selecting employee_id is allowed.Final Answer:
Missing parentheses around PARTITION BY clause in OVER(). -> Option BQuick Check:
OVER() requires parentheses [OK]
- Omitting parentheses in OVER()
- Thinking COUNT(*) can't be window function
- Assuming window functions require GROUP BY
Solution
Step 1: Understand cumulative count per customer
COUNT(*) OVER (PARTITION BY customer_id ORDER BY order_date) counts rows per customer in order of order_date cumulatively.Step 2: Check other options for correctness
SELECT customer_id, order_date, COUNT(*) FROM orders GROUP BY customer_id, order_date ORDER BY order_date; uses GROUP BY, not cumulative count; C lacks partition by customer; D partitions by order_date, not customer.Final Answer:
SELECT customer_id, order_date, COUNT(*) OVER (PARTITION BY customer_id ORDER BY order_date) AS cumulative_orders FROM orders; -> Option CQuick Check:
Use PARTITION BY customer_id with ORDER BY for cumulative count [OK]
- Missing PARTITION BY customer_id
- Using GROUP BY instead of window function
- Partitioning by wrong column
Ready to prove it?
Pass the test and this pattern moves unknown
