Window frame specification (ROWS BETWEEN) in SQL - Time & Space Complexity
When using window functions with a frame like ROWS BETWEEN, the database processes rows relative to the current one.
We want to understand how the work grows as the number of rows increases.
Analyze the time complexity of this SQL query using a window frame:
SELECT employee_id, salary,
AVG(salary) OVER (
ORDER BY employee_id
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW
) AS avg_salary
FROM employees;
This query calculates the average salary for each employee considering the current and two previous rows.
Look at what repeats as the query runs:
- Primary operation: For each row, calculate average over a small window of up to 3 rows.
- How many times: Once per row in the table.
As the number of rows grows, the work per row stays about the same because the window size is fixed.
| Input Size (n) | Approx. Operations |
|---|---|
| 10 | ~10 x 3 = 30 |
| 100 | ~100 x 3 = 300 |
| 1000 | ~1000 x 3 = 3000 |
Pattern observation: The total work grows linearly with the number of rows because the window size is fixed.
Time Complexity: O(n)
This means the total work grows in direct proportion to the number of rows in the table.
[X] Wrong: "Because the window looks at multiple rows, the time must grow much faster than the number of rows."
[OK] Correct: The window size is fixed and small, so each row only does a small, constant amount of work regardless of total rows.
Understanding how window frames affect performance helps you write efficient queries and explain your reasoning clearly in interviews.
"What if the window frame changed to ROWS BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW? How would the time complexity change?"
Practice
ROWS BETWEEN clause specify in a window function?Solution
Step 1: Understand window function frame
The window frame defines which rows are considered for each calculation in a window function.Step 2: Role of ROWS BETWEEN
TheROWS BETWEENclause specifies the exact range of rows relative to the current row to include in the calculation.Final Answer:
The range of rows to include relative to the current row for calculation -> Option AQuick Check:
ROWS BETWEEN controls row range = D [OK]
- Confusing ROWS BETWEEN with ORDER BY
- Thinking it filters rows from the table
- Mixing it up with GROUP BY
ROWS BETWEEN?Solution
Step 1: Understand frame boundaries order
The syntax isROWS BETWEEN X AND Ywhere X is the start and Y is the end of the frame.Step 2: Identify correct order for 2 rows before to current
Since 2 rows before is the start and current row is the end, it must beROWS BETWEEN 2 PRECEDING AND CURRENT ROW.Final Answer:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -> Option AQuick Check:
Start to end order matters = A [OK]
- Reversing the order of boundaries
- Using FOLLOWING instead of PRECEDING incorrectly
- Omitting CURRENT ROW keyword
sales(date, amount) ordered by date, what is the output of this query?SELECT date, amount, SUM(amount) OVER (ORDER BY date ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS running_sum FROM sales;
Assuming data:
date | amount
2024-01-01 | 100
2024-01-02 | 200
2024-01-03 | 300Solution
Step 1: Understand frame range
The frame includes the current row and 1 row before it, so for each row sum amounts of current and previous row.Step 2: Calculate running sums
Row 1: only 100 (no previous row), Row 2: 100+200=300, Row 3: 200+300=500.Final Answer:
[{"date": "2024-01-01", "amount": 100, "running_sum": 100}, {"date": "2024-01-02", "amount": 200, "running_sum": 300}, {"date": "2024-01-03", "amount": 300, "running_sum": 500}] -> Option CQuick Check:
Sum current + 1 preceding = A [OK]
- Including 2 rows before instead of 1
- Ignoring the order of rows
- Assuming NULL for first row sum
SELECT id, value, AVG(value) OVER (ORDER BY id ROWS BETWEEN CURRENT ROW AND 2 PRECEDING) AS avg_val FROM data;
Solution
Step 1: Check frame boundaries order
The frame must start with the earlier row and end with the later row. Here, CURRENT ROW is after 2 PRECEDING, so order is reversed.Step 2: Identify correct syntax
The correct syntax isROWS BETWEEN 2 PRECEDING AND CURRENT ROW, not the other way around.Final Answer:
The frame boundaries are reversed; start must be before end -> Option BQuick Check:
Frame start must be before end = C [OK]
- Swapping start and end boundaries
- Assuming PARTITION BY is mandatory
- Thinking ORDER BY disallows ROWS BETWEEN
Solution
Step 1: Understand difference between ROWS and RANGE
ROWScounts physical rows, whileRANGEcounts logical values like dates, which can skip rows if dates have gaps.Step 2: Choose frame to include 3 rows
UsingROWS BETWEEN 2 PRECEDING AND CURRENT ROWalways includes exactly 3 rows regardless of date gaps.Final Answer:
ROWS BETWEEN 2 PRECEDING AND CURRENT ROW -> Option DQuick Check:
ROWS counts rows, RANGE counts values = B [OK]
- Using RANGE which depends on value gaps
- Confusing FOLLOWING with PRECEDING
- Assuming RANGE counts rows
Ready to prove it?
Pass the test and this pattern moves unknown
