I have two tables - let's call them week
and contract
, like so:
Week Contract
emp_id | starting | data1 | ... emp_id | from_date | data2 | ...
-------|------------|-------|-- -------|------------|-------|--
12 | 2019-01-08 | abcd | 12 | 2018-08-01 | efgh |
12 | 2019-01-15 | abcd | 13 | 2018-10-02 | efgh |
12 | 2019-01-22 | abcd | 13 | 2019-01-15 | ijkl |
13 | 2019-01-08 | abcd | 13 | 2019-03-19 | mnop |
13 | 2019-01-15 | abcd | 14 | 2017-02-02 | efgh |
13 | 2019-01-22 | abcd | 15 | 2018-01-19 | efgh |
The week.starting
field is a date (datetime with time set to midnight) that's at fairly regular intervals. The specific combination of (emp_id, starting) is unique. The from_date
field is also a date that records the starting period where the contract
record applies. This can be in the future, so we can't just do a MAX(from)
and get the right contract for each employee. Currently, (emp_id, from_date) is unique, but I don't want to rely on this. week.starting
and contract.from_date
can be identical.
I want a query that returns the entire week
record, and for each, the record for whatever contract
was active at the time - that is, the record where from_date
is largest while still less than or equal to week.starting
. Getting this contract if I have a specific week in mind is a pretty straightforward greatest n-per-group problem:
SELECT * FROM contract
WHERE contract.emp_id = @emp_id AND contract.from_date <= @starting
ORDER BY contract.from_date DESC
LIMIT 1
But I can't work out how to do this as part of a query to get every record in week
. My specific combination of obstacles means I haven't been able to find an answer, despite this being a common set of problems. I don't appear to be able to pass week.starting
into a subquery, and I don't appear to be able to use LIMIT in a join either. My best attempt so far ended up joining all contracts that were less than a given week.
What query will return the result I'm looking for?
emp_id | starting | from_date | data1 | data2 | ...
-------|------------|------------|-------|-------|--
12 | 2019-01-08 | 2018-08-01 | abcd | efgh |
12 | 2019-01-15 | 2018-08-01 | abcd | efgh |
12 | 2019-01-22 | 2018-08-01 | abcd | efgh |
13 | 2019-01-08 | 2018-10-02 | abcd | efgh |
13 | 2019-01-15 | 2019-01-15 | abcd | ijkl |
13 | 2019-01-22 | 2019-01-15 | abcd | ijkl |