Skip to the solution
MediumDSA8 min read

What do the LAG and LEAD window functions do?

1.0k views

The problem

Question presented to candidate: "What do LAG and LEAD do? Say I have monthly revenue and I want each month next to the previous month and the change between them β€” how would you write it, and what happens on the first row?"

What a strong answer should cover:

  • LAG(expr) returns expr from the row before the current one in the window order, LEAD(expr) from the row after; both keep every row and replace a self join on "the previous row"
  • Full form LAG(expr, offset, default): offset is how many rows back (default 1), default is returned when that row does not exist (otherwise NULL, so the first row has no previous value)
  • They need ORDER BY in OVER to mean anything, and PARTITION BY to stop one entity (a user) reading another entity rows
  • Typical uses: period-over-period change, time between events per user, detecting state changes; filter on the result in an outer query
  • Gotchas: integer division in percentage change, the default must match the column type on PostgreSQL, and IGNORE NULLS is not available on PostgreSQL 16 or SQLite (SQL Server 2022 has it)

Code / implementation expected: Yes β€” previous and next value with the difference, plus a per-user version with PARTITION BY.

Schema used by the examples:

  • lag
  • lead

Try it yourself

Sketch your approach before you read the solution. That is what the interview tests.

Stuck? Get a hint.

A short nudge toward the approach. It will not give the answer away.

Solution

The solution is hidden so you can try first

8 min read Β· 12 sections

Run the code

Edit the query and run it against the tables for this question.

SQLEach month with the previous and next month revenue, the change and the % change
SQLThe offset and default arguments: two rows back, 0 instead of NULL, a label for the last row
SQLPARTITION BY user: days since the same user previous login (SQLite date maths)
PostgreSQL: returning users, away 7 days or more (filter on LAG in an outer query)
SELECT user_id, prev_login, login_date, login_date - prev_login AS days_away
FROM (
  SELECT user_id, login_date::date AS login_date,
         LAG(login_date::date) OVER (PARTITION BY user_id ORDER BY login_date) AS prev_login
  FROM logins
) AS t
WHERE login_date - prev_login >= 7
ORDER BY user_id, login_date;

Discussion

Other approaches, follow-ups and how it went in real interviews.

Sign in to join the discussion.

No comments yet. Share how you would answer it.

Question 27 of 82 in SQL

Keep your momentum going.

Mark this question solved to track your progress, then take the next one while it is fresh.

All SQL questions
Up nextMedium

How do you calculate year-over-year or month-over-month growth in SQL?

Continue