Reputation: 7099
I'm trying to use sqlite to join two tables with dates that don't perfectly match up.
For a given group/date in the left table, I want to join the corresponding record from the right table with the a date just before that of the left table. Probably easiest to show with an example.
table1:
group date teacher
a 1/10/00 1
a 2/27/00 1
b 1/7/00 1
b 4/5/00 1
c 2/9/00 2
c 9/12/00 2
table2:
teacher date hair length
1 1/1/00 4
1 1/5/00 8
1 1/30/00 20
1 3/20/00 100
2 1/1/00 0
2 8/10/00 50
Gives us:
group date teacher hair length
a 1/10/00 1 8
a 2/27/00 1 20
b 1/7/00 1 8
b 4/5/00 1 100
c 2/9/00 2 0
c 9/12/00 2 50
Upvotes: 0
Views: 1390
Reputation: 3196
If the hair length will always become longer by time, then you could do this:
select tablea.teachergroup, tablea.date, tablea.teacher,
max(tableb.hair_length)
from tablea
join tableb
on tablea.teacher=tableb.teacher
and tablea.date>=tableb.date
group by tablea.teachergroup, tablea.date, tablea.teacher
This could work for your sample data, but if hair length could become shorter, you have to :
select a.teachergroup, a.date, a.teacher,
tableb.hair_length
from (select tablea.teachergroup, tablea.date, tablea.teacher,
max(tableb.date) as tdate -- last date before group date
from tablea
join tableb
on tablea.teacher=tableb.teacher
and tablea.date>=tableb.date
group by tablea.teachergroup, tablea.date, tablea.teacher
) as a
join tableb
on a.teacher=tableb.teacher
and a.tdate=tableb.date
These are the efficient way I could do so far.
Upvotes: 1
Reputation: 2015
First of all, some sqlite statements for anyone trying to reproduce this problem:
create table tablea (teachergroup varchar(1), date datetime, teacher int);
insert into tablea (teachergroup, date, teacher) VALUES
('a','2000-01-10',1),('a','2000-02-27',1),
('b','2000-01-07',1),('b','2000-04-05',1),
('c','2000-02-09',2),('c','2000-09-12',2);
create table tableb (teacher int, date datetime, hair_length int);
insert into tableb (teacher, date, hair_length) VALUES
(1,'2000-01-01',4),(1,'2000-01-05',8),
(1,'2000-01-30',20),(1,'2000-03-20',100),
(2,'2000-01-01',0),(2,'2000-08-10',50);
Now, the most straightforward query (though certainly not a very performant one) would join the two tables like this:
select *
from tablea a
join tableb on a.teacher=b.teacher
and b.date in
(select max(date) from tableb where date < a.date and teacher=a.teacher);
Another thing you could do is join the tables a bit more liberally:
select * from a join b on a.teacher=b.teacher and b.date<a.date;
And then use any technique you would ordinarily use for getting the row that corresponds to the maximum date. (Like putting it into a temporary table, then getting the minimum date using a group by and then joining that back to the temporary table to get the row. I'm sure there are other ways.)
Upvotes: 1