lag returns the value of the row before the current one in the visual, in the order you give it. lead returns the row after. They are the building blocks for “change since the previous step”, for any sequence: weeks, funnel stages, versions, ranked products.

Copy and paste

Previous month’s sales:

lag(sum({Sales}), [truncDate('MM', {Order Date}) ASC], 1)

Previous value within each region:

lag(sum({Sales}), [truncDate('MM', {Order Date}) ASC], 1, [{Region}])

Change from the previous row:

sum({Sales}) - lag(sum({Sales}), [truncDate('MM', {Order Date}) ASC], 1)

Two rows back:

lag(sum({Sales}), [truncDate('MM', {Order Date}) ASC], 2)

Next row:

lead(sum({Sales}), [truncDate('MM', {Order Date}) ASC], 1)

Example

Month Sales Previous Change
Jan 2026 100
Feb 2026 120 100 20
Mar 2026 90 120 −30
Apr 2026 110 90 20

The first row has no previous row, so lag returns null and so does the change.

The arguments

lag(measure, [sort], lookup index, [partition]):

On MySQL, MariaDB and Aurora MySQL the lookup index is limited to 1.

Rows, not dates

lag counts rows. If a month has no sales it has no row, and the next month is compared with the month before the gap. For time series that is a silent error: use the period-over-period functions, which look up the previous date. Keep lag for sequences where position is the meaning: funnel steps, ranked items, consecutive events.

difference and percentDifference

difference and percentDifference take the same arguments as lag and return the change directly. Their reference pages describe a positive lookup index as a following row and a negative one as a previous row, so check the sign in a table before relying on the direction. Writing the subtraction with lag, as in the third formula, makes the direction visible in the formula itself.

Checked against the Amazon Quick Sight function reference (October 2026). The example results were recomputed in DuckDB.

References