Reputation: 6055
I have a table called trips
that looks like this:
id | vehicle_id | start_time | end_time |
----+------------+---------------------+---------------------+
1 | 1 | 2014-06-16 22:00:00 | 2014-06-24 03:30:00 |
2 | 1 | 2014-06-24 05:00:00 | 2014-06-28 05:00:00 |
3 | 2 | 2014-06-23 02:00:00 | 2014-06-30 04:00:00 |
...
SQL Fiddle: http://www.sqlfiddle.com/#!12/7c92e/1 (PG 9.2 only because 9.3 was overloaded on SQL Fiddle the time.)
start_time
and end_time
are both timestamps.
What I'd like to do find trips involving the same vehicle_id
where the start_time
of a subsequent trip takes place on the same calendar day or the next calendar day of the end_time
of a prior trip.
As an example, rows with ID 1
and 2
above would be returned, because:
2
's start_time
takes place on the same calendar day (2014-06-24
) as 1
; andvehicle_id
It's quite possible this isn't sensible to do in SQL. Any advice, tips or pointers to relevant Postgres functions welcome.
Upvotes: 0
Views: 243
Reputation:
Access to values from the "previous" row can be done using window functions. In this case the lag()
function.
select id, vehicle_id, start_time, end_time
from (
select id, vehicle_id, start_time, end_time,
start_time::date - lag(end_time::date) over (partition by vehicle_id order by start_time) as diff_to_prev,
end_time::date - lead(start_time::date) over (partition by vehicle_id order by start_time) as diff_to_next
from trips
) t
where diff_to_prev = 0
or diff_to_next = 0;
"previous" only make sense if you also supply a sort order. From your description it sounds as if you want to use the id
column to determine the order of the rows. But if you can easily change that to use start_date
.
The statement calculates the difference in days to the next row and the previous row. If only the difference to the previous was taken, the row with id=1
would not be returned.
The expression start_time::date
simply converts the timestamp to a date to remove the time part. This also has the effect that the difference is an integer value (in days) rather than an interval
.
SQLFiddle: http://www.sqlfiddle.com/#!12/7c92e/5
Upvotes: 2