First and Latest Salary Per Employee (FIRST_VALUE / LAST_VALUE)
For each employee in salaries_history, show every record alongside their first-ever salary and their latest salary. Beware the LAST_VALUE frame trap — use a full-partition frame. Return employee_id, effective_date, salary, first_salary, latest_salary — ordered by employee_id, effective_date.
- Window functions
- Sorting
Interview brief
Understand the request
For each employee in salaries_history, show every record alongside their first-ever salary and their latest salary. Beware the LAST_VALUE frame trap — use a full-partition frame. Return employee_id, effective_date, salary, first_salary, latest_salary — ordered by employee_id, effective_date.
Data you will use
Review the relevant tables before deciding how to join, filter, or aggregate them.
salaries_history
employee_idINTEGERsalaryINTEGEReffective_dateDATE
Hints, when you need them
Open one clue at a time so you still do the reasoning.
Hint 1
FIRST_VALUE is safe with the default frame; LAST_VALUE is NOT — the default frame ends at the current row.
Hint 2
Fix LAST_VALUE with ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING (the whole partition).
Hint 3
An alternative to LAST_VALUE is FIRST_VALUE with the ORDER BY reversed.
Verified SQL answer
Attempt the problem first, then compare structure and reasoning—not just syntax.
Reveal solution and explanation
SELECT employee_id, effective_date, salary, FIRST_VALUE(salary) OVER (PARTITION BY employee_id ORDER BY effective_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS first_salary, LAST_VALUE(salary) OVER (PARTITION BY employee_id ORDER BY effective_date ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) AS latest_salary FROM salaries_history ORDER BY employee_id, effective_date;Why this works
The LAST_VALUE frame trap is a classic interview gotcha. The default window frame is RANGE … CURRENT ROW, so LAST_VALUE returns the current row's value, not the partition's last. Always widen the frame to the full partition.
Expected result
Use this output to verify values, aliases, ordering, and row count.
| employee_id | effective_date | salary | first_salary | latest_salary |
|---|---|---|---|---|
| 4 | 2020-02-14 | 110000 | 110000 | 130000 |
| 4 | 2021-02-14 | 120000 | 110000 | 130000 |
| 4 | 2022-02-14 | 130000 | 110000 | 130000 |
| 5 | 2020-05-18 | 105000 | 105000 | 125000 |
| 5 | 2021-05-18 | 115000 | 105000 | 125000 |
| 5 | 2022-05-18 | 125000 | 105000 | 125000 |
| 6 | 2021-01-10 | 85000 | 85000 | 95000 |
| 6 | 2022-01-10 | 95000 | 85000 | 95000 |
| 8 | 2020-08-15 | 95000 | 95000 | 110000 |
| 8 | 2021-08-15 | 105000 | 95000 | 110000 |
Previewing 10 of 13 expected rows. Run the query in the editor to inspect the full result.
Learn the concepts behind this answer
Strengthen your understanding with these targeted learning topics: