FREE STUDY NOTES · DP-800

T-SQL window functions: OVER, PARTITION BY, ORDER BY and frames

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.

AVG(Amount) OVER (PARTITION BY AccountID ORDER BY TxnDate ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) is applied to two accounts. For the current row (account A, day 4) the frame covers days 2 to 4, giving (20 + 30 + 40) / 3 = 30, and the calculation starts again in account B. A note gives the default frame when ORDER BY is present: RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW.
Figure 4.1: The three parts of the OVER clause applied to 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.

Where window functions can appear

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:

Performance

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 after WHERE, so this fails; compute the number in a CTE and filter outside it (QUALIFY exists only in Fabric Data Warehouse and the SQL analytics endpoint).

Get the whole book

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.

Amazon.co.ukKindle: coming soonPaperback: coming soon
Amazon.comKindle: coming soonPaperback: coming soon

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

More DP-800 study notes