How the OVER clause partitions, orders and frames rows, and how ROWS and RANGE frames decide which rows each calculation sees.
From Ultra Transcenders DP-800 by Tony Rough (coming December 2026)
A window function computes a value for each row from a set of related rows (the window) without collapsing them the way GROUP BY does. The OVER clause defines the window with three optional parts: PARTITION BY, ORDER BY and a ROWS or RANGE frame. Figure 4.1 applies all three parts to a few sample rows.
Part of OVER |
Purpose | If omitted |
|---|---|---|
PARTITION BY |
Divides rows into groups; the calculation restarts per partition | The whole result set is one partition |
ORDER BY |
Logical order within each partition | Aggregate functions use every row in the partition |
ROWS/RANGE |
Frame of rows relative to the current row (requires ORDER BY) |
With ORDER BY present: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW for functions that accept a frame |
Window functions fall into four families: ranking (ROW_NUMBER, RANK, DENSE_RANK, NTILE), aggregate (SUM, AVG, COUNT, MIN, MAX and others with OVER), analytic (LAG, LEAD, FIRST_VALUE, LAST_VALUE, CUME_DIST, PERCENT_RANK, PERCENTILE_CONT, PERCENTILE_DISC) and NEXT VALUE FOR with a sequence.
The logical processing order of a SELECT is FROM, ON, JOIN, WHERE, GROUP BY, WITH CUBE/ROLLUP, HAVING, SELECT, DISTINCT, ORDER BY, TOP. Window functions are evaluated with the SELECT list, after WHERE, GROUP BY and HAVING, so they can be used in the select list and ORDER BY but not in WHERE. To filter on a window result, compute it in a CTE or derived table and filter in the outer query. Fabric Data Warehouse and the SQL analytics endpoint add a QUALIFY clause for this, but QUALIFY isn’t available in SQL Server, Azure SQL or SQL database in Fabric.
Other rules from the OVER clause reference:
PARTITION BY and the window ORDER BY can refer only to columns available from the FROM clause, not to select-list aliases, and the window ORDER BY can’t use a column position number.OVER can’t be combined with DISTINCT aggregates such as COUNT(DISTINCT col) OVER (...).OVER clauses can appear in one query.A rowstore index whose key is the PARTITION BY columns followed by the ORDER BY columns (in matching order), with the aggregated columns as INCLUDE columns, lets the engine avoid a sort. Window Aggregate operators can run in batch mode on tables with a columnstore index, or on rowstore tables at compatibility level 150 or higher; batch mode can’t be forced, so check the operator’s Actual Execution Mode. Accurate statistics on the partitioning and ordering columns, and memory grant feedback (compatibility level 140+), help avoid sort spills.
CREATE INDEX IX_OrderHeader_Customer_OrderDate
ON Sales.OrderHeader (CustomerID, OrderDate)
INCLUDE (TotalDue);
-- supports:
SELECT CustomerID, OrderDate,
SUM(TotalDue) OVER (PARTITION BY CustomerID ORDER BY OrderDate) AS RunningTotal
FROM Sales.OrderHeader;Common trap: Writing
WHERE ROW_NUMBER() OVER (...) = 1- window functions are evaluated afterWHERE, so this fails; compute the number in a CTE and filter outside it (QUALIFYexists only in Fabric Data Warehouse and the SQL analytics endpoint).
This note is one section of Ultra Transcenders DP-800: Developing AI-Enabled Database Solutions, an independent study guide that explains every topic the exam covers by technology, with comparison tables, diagrams and the common traps, plus a glossary linked to Microsoft Learn.
Due on Amazon in December 2026, in Kindle and paperback editions.
About the book · DP-800 terms in the glossary · All DP-800 study notes
How each isolation level trades consistency for concurrency, when to use RCSI or snapshot isolation, and which anomalies each one prevents.
How Always Encrypted keeps keys away from the database engine, deterministic versus randomised encryption, and secure enclaves.
How to build row-level security with an inline predicate function and a security policy, and how filter and block predicates differ.
How temporal tables keep row history automatically, and how FOR SYSTEM_TIME AS OF, BETWEEN and ALL query it.
When exact k-nearest-neighbour search is enough, when an approximate DiskANN vector index pays off, and why its metric must match the query.
How to combine full-text and vector search results with reciprocal rank fusion in T-SQL, and why RRF uses ranks rather than raw scores.
Choosing between change event streaming, change data capture, change tracking, Azure Functions and Logic Apps to react to row changes.