I'm trying to model a SQL table to store salary changes for employees. One approach is using a bi-temporal table as follows:
Here an employee was hired on 10/1/2015 with salary of 100,000. Then on 2/15/2016 he had a performance review and his boss said, "we're bumping your salary to 110,000 effective start of current year (1/1/2016).
To store this information, I'm using two sets of date ranges. The "effective" tells you when the salary was valid, e.g. $100k until 1/1/2016 and $110k from then on. On the other hand, the "settled" range indicates when the decision was made, in this case 2/15/2016. Thus I should be able to query for the following scenarios:
- what was his salary in Dec 2015 looking at the moment after salary review = old salary
- what was his salary on Jan 2, 2016 before he had the review = old salary (because employee didn't know about the raise yet)
- what was his salary on Jan 2, 2016 after he had the review = new salary (because employee now knows about the raise)
- etc
It seems I have two variables: effectiveOn, and settledOn. However, I'm struggling to come up with a SQL query that would produce the right results.
Here's what I've tried so far (does not work for all scenarios):
SELECT *
FROM Employees
WHERE (EmployeeId = 10)
AND
(
((SettledFrom <= @settledOn) AND (SettledTo IS NULL OR (SettledTo > @settledOn)))
AND ((EffectiveFrom <= @effectiveOn) AND (EffectiveTo IS NULL OR (EffectiveTo > @effectiveOn)))
)
Ideally I would need a SQL query that works in all scenarios and produces exactly one result row each time. Any help is greatly appreciated. Same for any improvements on the table design.