Salary history is the record of pay over time: one row for each change. The row names the employee, the amount, the currency, and the dates the amount is in effect, from and to.

One salary history row = one employee + one amount + one currency + one effective range

That is the definition used here. The history is the set of rows. A single number stored on the person is a smaller fact: the pay in effect now, after the earlier rows have been discarded.

A current salary forgets the previous one

A field that holds only the current salary can answer “what is this person paid now?” Updating it answers that question by replacing the previous amount. The earlier pay is gone, so “what were they paid on this date?” no longer has a row to return.

Salary history keeps each change. In this made-up example, Rowan works at a fictional studio:

  • From 2024-01-01 until 2025-01-01: USD 4,000.
  • From 2025-01-01 until 2026-01-01: USD 4,200.
  • From 2026-01-01, with no end yet: USD 4,500.

Three changes, three rows, one employee. The amount is a money amount, so the currency stays on the row. A column that stores only the salary amount still needs a currency, either beside it or as context that covers that row. Currency is part of the number.

A department assignment has the same shape and a different subject. Rowan can move from design to operations on a date. That move is its own dated row. It does not belong inside the salary row, and the salary change does not belong in a column on the employee that gets overwritten. The person guide separates the human from the employment role. Pay history is a fact about that role across time.

Salary as of a date

“What was Rowan paid on 1 June 2025?” reads the ranges. In the example, 2025-06-01 falls in the second row, so the answer is USD 4,200. The open row of USD 4,500 is the current salary. It is the wrong row for that day.

This sketch treats the start as inclusive and the end as exclusive. A null end means the row is still open. The date in the query is the example’s as-of day. The names are generic. They are not a table from the Employees sample or any other database.

select amount, currency_code
from salary_history
where employee_id = :employee_id
  and effective_from <= date '2025-06-01'
  and (effective_to is null or effective_to > date '2025-06-01');

The predicate should return the one row whose range contains the as-of date. If a model stores a closed end instead, the comparison is effective_to >= that date. Record which convention the table uses. Mixing the two shifts the result on the day a raise starts.

Overlaps, open rows, and currency changes

Overlapping periods. Two of Rowan’s rows that both contain 2025-06-01 do not define one salary. The as-of query is then allowed to return two amounts. Close the previous range when the next one starts, and reject a load that leaves an overlap.

The open current row. The row in force today needs an end that means “still in effect”: a null, or a sentinel the dataset documents. A report that reads the sentinel as a real end date invents a future. A report that drops null ends omits everyone whose pay has not finished. When a new amount starts, close the previous row so two current rows do not both match today.

A currency that changes or goes missing. USD 4,000 and USD 4,200 can be compared because the unit matches. Reading the open row as EUR 4,500 does not make a raise of 300 from USD 4,200: the unit changed. These figures are illustrative. Convert with a stated rate, direction, and rate date, or keep the currencies in separate totals. A symbol such as “$” does not name the currency.

How the Employees sample states it

In the Employees sample, employee salary history is this entity: a salary value and an effective date range for a selected employee. The registered meaning says the upstream source declares no currency. The salary amount there is the integer the sample provides. It is not, by itself, a money amount with a unit. Leave those rows without an invented currency.

Department assignment in the same graph is the parallel dated fact: which department, from when, until when. Employee means a person employed by an organization. The sample’s employee row is linked to the salary history. It does not hold one salary cell that replaces itself.

A usable answer names the employee, the amount, the currency, and the dates. “Rowan’s salary” is unfinished. “USD 4,200 for Rowan from 2025-01-01 until 2026-01-01” is a row someone else can look up again.