Reputation: 1455
I know the "how to join the newest record" questions get asked a lot, however, this one exceeds my knowledge. I usually use a "join the max date subquery and then join the row with the matching id and time" approach to the problem, and I can add additional conditions in the where clause of the subquery, but this style doesn't work in this situation.
I am looking for a history of all records in the first table, and to join on the most recent record from the second table before the time of the record from the first.
Example:
CREATE TABLE `A` (
`id` int(11) NOT NULL,
`a_time` timestamp NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `A` (`id`, `a_time`) VALUES
(1, '2018-03-21 04:30:00'),
(2, '2018-03-21 05:30:00'),
(3, '2018-03-21 07:30:00'),
(4, '2018-03-21 12:30:00');
CREATE TABLE `B` (
`id` int(11) NOT NULL,
`b_time` timestamp NOT NULL,
`some_text` varchar(128) NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
INSERT INTO `B` (`id`, `b_time`, `some_text`) VALUES
(1, '2018-03-21 05:30:00', 'Foo'),
(2, '2018-03-21 09:30:00', 'Bar');
ALTER TABLE `A`
ADD PRIMARY KEY (`id`);
ALTER TABLE `B`
ADD PRIMARY KEY (`id`);
What I'm hoping for is the id and time from A, and the most recent (<=) some_text from B
a.id a.a_time b.some_text
------------------------------------
1 2018-03-21 04:30:00 null
2 2018-03-21 05:30:00 Foo
3 2018-03-21 07:30:00 Foo
4 2018-03-21 12:30:00 Bar
Can someone help me out with this one? Thanks!
Upvotes: 0
Views: 23
Reputation: 33945
I might use an uncorellated subquery, like this:
SELECT x.some
, c.columns
, y.some_column
FROM
( SELECT a.*
, MAX(b.b_time) b_time
FROM a
LEFT
JOIN b
ON b.b_time <= a.a_time
GROUP
BY id
) x
LEFT
JOIN b y
ON y.something = x.something;
+----+---------------------+-----------+
| id | a_time | some_text |
+----+---------------------+-----------+
| 1 | 2018-03-21 04:30:00 | NULL |
| 2 | 2018-03-21 05:30:00 | Foo |
| 3 | 2018-03-21 07:30:00 | Foo |
| 4 | 2018-03-21 12:30:00 | Bar |
+----+---------------------+-----------+
Upvotes: 1
Reputation: 35583
I would use a "correlated subquery" like this:
Query 1:
select
a.*
, (select b.some_text from b
where b.b_time <= a.a_time
order by b.b_time DESC
limit 1) as some_text
from a
order by a.id
| id | a_time | some_text |
|----|----------------------|-----------|
| 1 | 2018-03-21T04:30:00Z | (null) |
| 2 | 2018-03-21T05:30:00Z | Foo |
| 3 | 2018-03-21T07:30:00Z | Foo |
| 4 | 2018-03-21T12:30:00Z | Bar |
Upvotes: 1