Window Frame (ROWS/RANGE)

SQL · Window Functions

Theory

A frame narrows the window to a slice of the partition measured from the current row. You write it after ORDER BY, for example ROWS BETWEEN 2 PRECEDING AND CURRENT ROW (this row and the two before it, a 3-row moving window) or ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING (the whole partition). The boundary words are UNBOUNDED PRECEDING, n PRECEDING, CURRENT ROW, n FOLLOWING and UNBOUNDED FOLLOWING.

ROWS counts physical rows. RANGE works on values of the ORDER BY column, so all rows with the same value as the current row are 'peers' and are included together. When you write ORDER BY without any frame, the default is RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW. That is why two orders on the same date both show the same running total under the default, while ROWS gives each its own step. Frames apply to aggregates and FIRST_VALUE/LAST_VALUE/NTH_VALUE; ranking functions and LAG/LEAD ignore them.

Why we use it

Frames let you answer 'last 3 months', 'everything so far' or 'the whole group' with the same function. They turn SUM and AVG into running totals and moving averages without any self-joins.

When to use it

Use ROWS for moving averages and exact row-by-row running totals. Use RANGE when tied values should be treated as one step (or for value ranges where supported). Always write the frame explicitly when results with ties or LAST_VALUE look odd.

How it works

  1. Partition is sorted by the window ORDER BY
  2. Take the current row
  3. Frame type ROWS? Yes: Count n physical rows around this row. No: RANGE: include equal-value peers.
  4. Collect the rows inside the frame boundaries
  5. Apply the function to only those rows
  6. Move to the next row and slide the frame

Syntax

function() OVER (
  ORDER BY column
  ROWS BETWEEN n PRECEDING AND CURRENT ROW
)

Example

SELECT name, salary,
  SUM(salary) OVER (ORDER BY id ROWS BETWEEN 1 PRECEDING AND CURRENT ROW) AS running_2
FROM employees;

Key points

SQL topics

Introduction to SQL

Querying Data

Sorting Rows

Limiting Rows

Filtering Rows

Joining Multiple Tables

Grouping Rows

SET Operators

Working with Tables

Modifying Data

Views & Triggers

Conditional Expressions

SQL Subqueries

Aggregate Functions

Window Functions

String Functions

Date Functions

Math Functions

Extra Concepts

T
Tech Town
Log InSign Up Free
Home SQL Python DSA Power BI Snowflake Databricks Spark Gen AI Practice Problems Contest Blog

Master SQL from Zero to Pro

All SQL topics in one place. Click any topic in the sidebar — content opens right here without leaving the page.

{{ sectionCount }}
Sections
{{ topicCount }}
Topics
Free
Forever
Hands-on practice Practice SQL Online Solve 150 SQL interview problems in a live editor with instant checking. Start practising →
Section {{ sec.num }}

{{ sec.label }}

SQL  /  {{ current.sectionLabel }}  /  {{ current.name }}

{{ current.name }}

Theory

{{ current.def }}

Why we use it

{{ rich.why }}

When to use it

{{ rich.when }}

Diagram

{{ rich.dg.caption }}

{{ tb.title }}
{{ c.v }}
{{ rich.dg.op }}
➜
{{ rich.dg.output.title }}
{{ c.v }}
{{ nd.label }}
{{ nd.sub }}
{{ nd.label }}
{{ nd.sub }}
{{ rich.dg.left.title }}
{{ it }}
{{ rich.dg.right.title }}
{{ it }}
Flowchart — how it works
{{ nd.text }}
{{ nd.text }}
◇ {{ nd.text }}
Yes → {{ nd.yes }}
No → {{ nd.no }}
Syntax
{{ current.syntax }}
Example
{{ current.example }}
▶ Try It Live — runs against a real sample database
{{ liveError }}
{{ col }}
{{ cell }}
Key Points — click to check off as you learn
  • {{ pt.mark }} {{ pt.text }}

Share this topic