Skip to content

LAG and LEAD in SQL Server: Simple Examples

10a - LAG and LEAD  (VERY SIMPLE version)
---------------------------------------------------------------------
No setup needed. This file creates its own small table.

LAG = look at the PREVIOUS row LEAD = look at the NEXT row

LAG(column) OVER (ORDER BY some_column) LEAD(column) OVER (ORDER BY some_column)

Run the sample database script first. Every query below was run on that data, and the Output under each query is the real result.

IF DB_ID('SqlLearningDb') IS NULL
    CREATE DATABASE SqlLearningDb;
GO

USE SqlLearningDb;
GO

Small table: sales of one shop for 6 months

DROP TABLE IF EXISTS dbo.ShopSales;

CREATE TABLE dbo.ShopSales
(
    SaleMonth INT,          -- 1 = Jan, 2 = Feb ...
    MonthName VARCHAR(10),
    Amount    INT
);

INSERT INTO dbo.ShopSales (SaleMonth, MonthName, Amount) VALUES
(1, 'Jan', 1000),
(2, 'Feb', 1500),
(3, 'Mar', 1200),
(4, 'Apr', 1800),
(5, 'May', 1700),
(6, 'Jun', 2000);
GO

SELECT * FROM dbo.ShopSales;
Messages
(6 rows affected)
Output
SaleMonthMonthNameAmount
1Jan1000
2Feb1500
3Mar1200
4Apr1800
5May1700
6Jun2000

LAG: previous month's amount

Jan has no previous month, so it shows NULL

SELECT MonthName,
       Amount,
       LAG(Amount) OVER (ORDER BY SaleMonth) AS PreviousMonth
FROM dbo.ShopSales;
Output
MonthNameAmountPreviousMonth
Jan1000NULL
Feb15001000
Mar12001500
Apr18001200
May17001800
Jun20001700

LEAD: next month's amount

Jun has no next month, so it shows NULL

SELECT MonthName,
       Amount,
       LEAD(Amount) OVER (ORDER BY SaleMonth) AS NextMonth
FROM dbo.ShopSales;
Output
MonthNameAmountNextMonth
Jan10001500
Feb15001200
Mar12001800
Apr18001700
May17002000
Jun2000NULL

LAG and LEAD together

SELECT MonthName,
       LAG(Amount)  OVER (ORDER BY SaleMonth) AS PreviousMonth,
       Amount                                 AS ThisMonth,
       LEAD(Amount) OVER (ORDER BY SaleMonth) AS NextMonth
FROM dbo.ShopSales;
Output
MonthNamePreviousMonthThisMonthNextMonth
JanNULL10001500
Feb100015001200
Mar150012001800
Apr120018001700
May180017002000
Jun17002000NULL

Show 0 instead of NULL (third value = default)

SELECT MonthName,
       Amount,
       LAG(Amount, 1, 0) OVER (ORDER BY SaleMonth) AS PreviousMonth
FROM dbo.ShopSales;
Output
MonthNameAmountPreviousMonth
Jan10000
Feb15001000
Mar12001500
Apr18001200
May17001800
Jun20001700

Go back 2 rows instead of 1 (second value = how many rows)

SELECT MonthName,
       Amount,
       LAG(Amount, 2) OVER (ORDER BY SaleMonth) AS TwoMonthsAgo
FROM dbo.ShopSales;
Output
MonthNameAmountTwoMonthsAgo
Jan1000NULL
Feb1500NULL
Mar12001000
Apr18001500
May17001200
Jun20001800

Difference from last month (most common use of LAG)

SELECT MonthName,
       Amount,
       LAG(Amount) OVER (ORDER BY SaleMonth)          AS PreviousMonth,
       Amount - LAG(Amount) OVER (ORDER BY SaleMonth) AS Difference
FROM dbo.ShopSales;
Output
MonthNameAmountPreviousMonthDifference
Jan1000NULLNULL
Feb15001000500
Mar12001500-300
Apr18001200600
May17001800-100
Jun20001700300

Did sales go Up or Down?

SELECT MonthName,
       Amount,
       CASE
           WHEN Amount > LAG(Amount) OVER (ORDER BY SaleMonth) THEN 'UP'
           WHEN Amount < LAG(Amount) OVER (ORDER BY SaleMonth) THEN 'DOWN'
           ELSE '-'
       END AS Trend
FROM dbo.ShopSales;
Output
MonthNameAmountTrend
Jan1000-
Feb1500UP
Mar1200DOWN
Apr1800UP
May1700DOWN
Jun2000UP

Practice Questions

  1. Show each month with the NEXT month's name (use LEAD on MonthName).
  2. Show how much sales will change from this month to next month (use LEAD).
  3. Show the amount from 3 months ago.