Summary: in this tutorial, you will learn how to access data of a previous row from the current row using the SQL LAG()
function.
Overview of SQL LAG() function
SQL LAG()
is a window function that provides access to a row at a specified physical offset which comes before the current row.
In other words, by using the LAG()
function, from the current row, you can access data of the previous row, or from the second row before the current row, or from the third row before current row, and so on.
The LAG()
function can be very useful for calculating the difference between the current row and the previous row.
The following illustrates the syntax of the LAG()
function:
LAG(return_value [,offset[, default_value ]]) OVER (
PARTITION BY expr1, expr2,...
ORDER BY expr1 [ASC | DESC], expr2,...
)
Code language: SQL (Structured Query Language) (sql)
Let’s examine each element of the LAG()
function in more detail.
return_value
The return value based on the specified offset. It can be a column of the row at a given offset from the current row.
offset
The number of rows back from the current row from which to access data. The offset must be a non-negative integer. It defaults to one if skipped.
default_value
If the preceding row is not specified, default_value
is returned. For example, when the offset is 2, the return value from the first row is default_value
. If default_value
is not given and no preceding row found, NULL is returned by default.
PARTITION BY clause
The PARTITION BY
clause organizes rows into one or more partitions to which the LAG()
function is applied. The whole result is treated as a single partition if you omit the PARTITION BY
clause.
ORDER BY clause
The ORDER BY
clause specifies the order of rows in each partition to which the LAG()
function is applied.
SQL LAG() function example
We will create a new table named basic_pays
that stores the salary history of employees:
CREATE TABLE basic_pays (
employee_id int,
fiscal_year INT,
salary DECIMAL(10 , 2 ),
PRIMARY KEY (employee_id, fiscal_year)
);
Code language: SQL (Structured Query Language) (sql)
The following script inserts data into the basic_pays
table:
INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(100,2017,24000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(101,2017,17000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(102,2017,17000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(103,2017,9000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(104,2017,6000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(105,2017,4800); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(106,2017,4800); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(107,2017,4200); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(108,2017,12000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(109,2017,9000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(110,2017,8200); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(111,2017,7700); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(112,2017,7800); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(113,2017,6900); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(114,2017,11000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(115,2017,3100); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(116,2017,2900); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(117,2017,2800); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(118,2017,2600); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(119,2017,2500); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(120,2017,8000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(121,2017,8200); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(122,2017,7900); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(123,2017,6500); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(126,2017,2700); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(145,2017,14000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(146,2017,13500); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(176,2017,8600); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(177,2017,8400); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(178,2017,7000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(179,2017,6200); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(192,2017,4000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(193,2017,3900); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(200,2017,4400); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(201,2017,13000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(202,2017,6000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(203,2017,6500); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(204,2017,10000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(205,2017,12000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(206,2017,8300); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(100,2018,25920); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(101,2018,18190); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(102,2018,18360); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(103,2018,9720); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(104,2018,6060); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(105,2018,4992); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(106,2018,5040); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(107,2018,4284); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(108,2018,12360); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(109,2018,9540); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(110,2018,8692); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(111,2018,7931); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(112,2018,8580); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(113,2018,7107); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(114,2018,11440); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(115,2018,3131); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(116,2018,3161); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(117,2018,2940); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(118,2018,2652); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(119,2018,2650); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(120,2018,8800); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(121,2018,8364); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(122,2018,8611); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(123,2018,6565); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(126,2018,2808); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(145,2018,14560); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(146,2018,14580); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(176,2018,9202); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(177,2018,8988); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(178,2018,7630); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(179,2018,6448); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(192,2018,4320); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(193,2018,4173); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(200,2018,4620); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(201,2018,13000); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(202,2018,6360); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(203,2018,7085); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(204,2018,10100); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(205,2018,12360); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(206,2018,8632); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(100,2020,26179.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(101,2020,19463.3); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(102,2020,19278); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(103,2020,10206); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(104,2020,6605.4); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(105,2020,5391.36); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(106,2020,5191.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(107,2020,4498.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(108,2020,13472.4); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(109,2020,9826.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(110,2020,9561.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(111,2020,8248.24); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(112,2020,9352.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(113,2020,7107); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(114,2020,12012); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(115,2020,3224.93); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(116,2020,3287.44); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(117,2020,3175.2); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(118,2020,2864.16); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(119,2020,2782.5); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(120,2020,9152); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(121,2020,8531.28); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(122,2020,8697.11); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(123,2020,6630.65); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(126,2020,2920.32); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(145,2020,16016); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(146,2020,14871.6); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(176,2020,9938.16); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(177,2020,9167.76); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(178,2020,7858.9); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(179,2020,6641.44); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(192,2020,4406.4); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(193,2020,4339.92); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(200,2020,4712.4); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(201,2020,14040); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(202,2020,6614.4); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(203,2020,7155.85); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(204,2020,10908); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(205,2020,12730.8); INSERT INTO basic_pays(employee_id, fiscal_year,salary) VALUES(206,2020,8890.96);
A) Using SQL LAG() function over partitions example
The following statement returns both the current and previous year’s salary of all employees:
SELECT
employee_id,
fiscal_year,
salary,
LAG(salary) OVER (
PARTITION BY employee_id
ORDER BY fiscal_year) previous_salary
FROM
basic_pays;
Code language: SQL (Structured Query Language) (sql)
The following is the partial output:
In this example:
- First, the
PARTITION BY
clause divided the result set into groups by employee ID. - Second, for each group, the
ORDER BY
clause sorted the rows by fiscal year in ascending order. - Third,
LAG()
function applied to the row of each group independently. The first row in each group wasNULL
because there was no previous year’s salary. The second and third row gots the salary from the first and second row and populated them into theprevious_salary
column.
You can find the YoY salary increment by using the following query:
SELECT
employee_id,
fiscal_year,
salary,
previous_salary,
CONCAT(ROUND(( salary - previous_salary ) * 100 /previous_salary,0),'%') YoY
FROM
( SELECT
employee_id,
fiscal_year,
salary,
LAG(salary,1,0) OVER (
PARTITION BY employee_id
ORDER BY fiscal_year) previous_salary
FROM
basic_pays
) t;
Code language: SQL (Structured Query Language) (sql)
The following picture shows the partial output:
In this tutorial, you have learned how to use the SQL LAG()
function to access data of the previous row from the current row.