Percent of total with window functions in SQL - Time & Space Complexity
When we use window functions to calculate percent of total, we want to know how the work grows as the data grows.
How does the time to run the query change when the number of rows increases?
Analyze the time complexity of the following SQL query using window functions.
SELECT
category,
sales,
sales * 100.0 / SUM(sales) OVER () AS percent_of_total
FROM
sales_data;
This query calculates each category's sales and what percent it is of the total sales.
Look for repeated work done by the query.
- Primary operation: Scanning all rows once to compute the total sales and then computing percent for each row.
- How many times: The total sum is computed once, and then each row is processed once to calculate the percent.
As the number of rows grows, the total sum calculation scans all rows once, then each row gets its percent calculated.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | About 20 operations (10 to sum, 10 to calculate percent) |
| 100 | About 200 operations |
| 1000 | About 2000 operations |
Pattern observation: The work grows roughly in direct proportion to the number of rows.
Time Complexity: O(n)
This means the time to run the query grows linearly as the number of rows increases.
[X] Wrong: "Using window functions means the query runs multiple times for each row, so it's much slower than a simple sum."
[OK] Correct: The window function computes the total sum once over all rows, then applies the calculation per row without repeating the full sum each time.
Understanding how window functions scale helps you explain query performance clearly and shows you know how databases handle calculations efficiently.
What if we changed the window function to partition by category? How would the time complexity change?
Practice
SUM(column) OVER () compute in a query?Solution
Step 1: Understand window function syntax
The syntaxSUM(column) OVER ()means sum over all rows without partitioning or grouping.Step 2: Compare with GROUP BY sum
Unlike GROUP BY, this sums the entire column across all rows, returning the same total for each row.Final Answer:
The total sum of the column across all rows without grouping -> Option BQuick Check:
SUM() OVER () = total sum [OK]
- Confusing window sum with GROUP BY sum
- Thinking it calculates average
- Assuming it returns max value
Solution
Step 1: Identify correct window function usage
SELECT product, sales, (sales / SUM(sales) OVER ()) * 100 AS percent_total FROM sales_table; usesSUM(sales) OVER ()to get total sales across all rows, then divides each sales value by this total.Step 2: Check other options for errors
SELECT product, sales, (SUM(sales) OVER () / sales) * 100 AS percent_total FROM sales_table; divides total by sales (wrong direction). SELECT product, sales, (sales / SUM(sales)) * 100 AS percent_total FROM sales_table GROUP BY product; uses SUM(sales) without OVER(), which requires GROUP BY and won't work as intended. SELECT product, sales, (sales / COUNT(*) OVER ()) * 100 AS percent_total FROM sales_table; divides sales by count of rows, not sum.Final Answer:
SELECT product, sales, (sales / SUM(sales) OVER ()) * 100 AS percent_total FROM sales_table; -> Option AQuick Check:
Percent = sales / total sales * 100 [OK]
- Reversing numerator and denominator
- Using SUM() without OVER() in window context
- Using COUNT() instead of SUM() for total
sales_data with columns product and amount, what is the output of this query?SELECT product, amount, ROUND((amount / SUM(amount) OVER ()) * 100, 1) AS percent_total FROM sales_data ORDER BY product;
Assume the data:
product | amount
-------|-------
A | 50
B | 30
C | 20Solution
Step 1: Calculate total amount
Total = 50 + 30 + 20 = 100.Step 2: Calculate percent for each product
Percent = (amount / total) * 100 rounded to 1 decimal:
A: (50/100)*100 = 50.0
B: (30/100)*100 = 30.0
C: (20/100)*100 = 20.0Final Answer:
[{"product": "A", "amount": 50, "percent_total": 50.0}, {"product": "B", "amount": 30, "percent_total": 30.0}, {"product": "C", "amount": 20, "percent_total": 20.0}] -> Option DQuick Check:
Percent totals sum to 100% [OK]
- Not rounding results
- Using COUNT() instead of SUM()
- Calculating percent incorrectly (e.g., reversed division)
SELECT product, sales, (sales / SUM(sales)) * 100 AS percent_total FROM sales_table;
But it gives an error. What is the problem?
Solution
Step 1: Analyze use of SUM() without OVER()
SUM(sales) without GROUP BY or window function context causes error because SQL doesn't know how to aggregate without grouping.Step 2: Correct usage
Use either GROUP BY product with SUM(sales) or use window function SUM(sales) OVER () to get total sum without grouping.Final Answer:
SUM(sales) requires a GROUP BY clause or window function syntax -> Option AQuick Check:
SUM() needs GROUP BY or OVER() [OK]
- Ignoring need for GROUP BY with aggregate functions
- Assuming multiplication by 100 causes error
- Thinking WHERE clause is mandatory here
orders with columns category and amount. Write a query to show each category, total amount per category, and percent of total amount across all categories. Which query is correct?Solution
Step 1: Calculate total per category
UseSUM(amount) GROUP BY categoryto get total per category.Step 2: Calculate percent of total across all categories
Use window functionSUM(SUM(amount)) OVER ()to get grand total across all categories, then divide category total by this and multiply by 100.Step 3: Verify query correctness
SELECT category, SUM(amount) AS category_total, (SUM(amount) / SUM(SUM(amount)) OVER ()) * 100 AS percent_total FROM orders GROUP BY category ORDER BY category; correctly combines GROUP BY with window function for total sum. SELECT category, amount, (amount / SUM(amount) OVER ()) * 100 AS percent_total FROM orders ORDER BY category; uses amount per row, not category total. SELECT category, SUM(amount) AS category_total, (SUM(amount) / COUNT(*) OVER ()) * 100 AS percent_total FROM orders GROUP BY category; incorrectly uses COUNT() for total. SELECT category, SUM(amount) AS category_total, (SUM(amount) / SUM(amount)) * 100 AS percent_total FROM orders GROUP BY category; divides sum by itself, always 100%.Final Answer:
SELECT category, SUM(amount) AS category_total, (SUM(amount) / SUM(SUM(amount)) OVER ()) * 100 AS percent_total FROM orders GROUP BY category ORDER BY category; -> Option CQuick Check:
Percent = category sum / total sum * 100 [OK]
- Using row amount instead of category sum
- Using COUNT() instead of SUM() for total
- Dividing sum by itself always gives 100%
Ready to prove it?
Pass the test and this pattern moves unknown
