Reputation: 327
I have a table similar to this one, representing which drivers were driving different cars at certain times.
CAR_ID DRIVER_ID DT
10 A 10:00
10 A 12:00
10 A 14:00
10 B 16:00
10 B 17:00
10 B 20:00
10 A 21:00
10 A 22:00
20 C 15:00
20 C 18:00
Where DT
is a datetime. I'm trying to have something similar to what I would obtain using a DENSE_RANK()
function but generating a new number when there is a change on the column DRIVER_ID
between two drivers. This would be my expected output:
CAR_ID DRIVER_ID DT RES
10 A 10:00 1
10 A 12:00 1
10 A 14:00 1
10 B 16:00 2
10 B 17:00 2
10 B 20:00 2
10 A 21:00 3 #
10 A 22:00 3 #
20 C 15:00 4
20 C 18:00 4
Using DENSE_RANK() OVER (PARTITION BY CAR_ID, DRIVER_ID ORDER BY DT) AS RES
I get the two elements marked with a # as members of the same group as the first three rows, but I want them to be different, because of the "discontinuity" (the car was driven by another driver from 16:00 to 20:00). I can't seem to find a solution that doesn't include a loop. Is this possible?
Any help would be greatly appreciated.
Upvotes: 2
Views: 46
Reputation: 960
You need to do.a row_number partitioned by car and ordered by dt. Also you need to do a row_number partitioned by car and driver and ordered by dt. Subtracting the second of these from the first gives you a unique "segment" number - which in this case will represent the continuous period of possession that each driver had of each car.
This segment number value has no Intrinsic meaning - it is just guaranteed to be different for each segment within the partition of cars and drivers. Then use this segment number as an additional partition for whatever function you are trying to apply.
As a note, however, I couldn't work out how you got the results you've displayed for RES
from the code you quote, and thus I'm not exactly sure what you are trying to achieve overall.
Upvotes: 1
Reputation: 49260
This can be done with lag
and running sum.
select t.*,sum(case when prev_driver = driver then 0 else 1 end) over(partition by id order by dt) as res
from (select t.*,lag(driver_id) over(partition by id order by dt) as prev_driver
from tbl
) t
Upvotes: 2