LAG() accesses a previous row\'s value; LEAD() accesses a next row\'s value — both without a self-join.
-- Syntax: LAG(column, offset, default) OVER (PARTITION BY ... ORDER BY ...)
-- Month-over-month sales comparison
SELECT
SaleMonth,
TotalSales,
LAG(TotalSales, 1, 0) OVER (ORDER BY SaleMonth) AS PrevMonthSales,
LEAD(TotalSales, 1, 0) OVER (ORDER BY SaleMonth) AS NextMonthSales,
TotalSales - LAG(TotalSales, 1, 0) OVER (ORDER BY SaleMonth) AS MoM_Change
FROM (
SELECT FORMAT(OrderDate, 'yyyy-MM') AS SaleMonth,
SUM(Amount) AS TotalSales
FROM Orders
GROUP BY FORMAT(OrderDate, 'yyyy-MM')
) m
ORDER BY SaleMonth;
-- Partition by region: compare to previous month within each region
SELECT Region, SaleMonth, TotalSales,
LAG(TotalSales) OVER (PARTITION BY Region ORDER BY SaleMonth) AS PrevSales,
TotalSales - LAG(TotalSales) OVER (PARTITION BY Region ORDER BY SaleMonth) AS Diff
FROM (
SELECT Region, FORMAT(OrderDate, 'yyyy-MM') AS SaleMonth,
SUM(Amount) AS TotalSales
FROM Orders
GROUP BY Region, FORMAT(OrderDate, 'yyyy-MM')
) t;
-- Detect gaps in sequential IDs
WITH Gaps AS (
SELECT OrderID,
OrderID - LAG(OrderID) OVER (ORDER BY OrderID) AS GapSize
FROM Orders
)
SELECT * FROM Gaps WHERE GapSize > 1;
↥ back to top