Window syntax in T-SQL
Create the window with OVER clause
PARTITION BY creates the frame
If you do not include PARTITION BY , the entire table is used as the frame.
To arrange the result, use ORDER BY
Allows aggregations to be created at the same time with the window.
SELECT OrderID, TerritoryName,
-- Total price for each partition
SUM(OrderPrice)
-- Create the window and partitions
OVER(PARTITION BY TerritoryName) AS TotalPrice
FROM Orders
There are four window functions; FIRST_VALUE(), LAST_VALUE(), LAG() and LEAD().
FIRST_VALUE(): returns the first value in a window.
LAST_VALUE(): returns the last value in a window.
LAG(): returns the previous value in partitioned condition. Note that the lag value will always be null for the first value.
LEAD(): returns the next value in the partitioned condition. Note that the lead value will always be NULL for the last window.
Use cases;
SELECT TerritoryName, OrderDate,
#Select the first value in each partition
FIRST_VALUE(OrderDate)
#Create the partitions and arrange the rows
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS FirstOrder
FROM Orders
SELECT TerritoryName, OrderDate,
#Specify the previous OrderDate in the window
LAG(OrderDate)
#Over the window, partition by territory & order by order date
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS PreviousOrder,
#Specify the next OrderDate in the window
LEAD(OrderDate)
#Create the partitions and arrange the rows
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS NextOrder
FROM Orders
You can also use aggregate function.
Use Case;
SELECT TerritoryName, OrderDate,
#Create a running total
SUM(OrderPrice)
#Create the partitions and arrange the rows
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS TerritoryTotal
FROM Orders
SELECT TerritoryName, OrderDate,
#Assign a row number
ROW_NUMBER()
#Create the partitions and arrange the rows
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS OrderCount
FROM Orders
SELECT OrderDate, TerritoryName,
#Calculate the standard deviation
STDEV(OrderPrice)
OVER(PARTITION BY TerritoryName ORDER BY OrderDate) AS StdDevPrice
FROM Orders
#Create a CTE Called ModePrice which contains two columns
WITH ModePrice (OrderPrice, UnitPriceFrequency)
AS
(
SELECT OrderPrice,
ROW_NUMBER()
OVER(PARTITION BY OrderPrice ORDER BY OrderPrice) AS UnitPriceFrequency
FROM Orders
)
#Select everything from the CTE
SELECT * FROM ModePrice