I have been handed an (ancient) database in SQLServer format containing rental records. These records can be modified by the customer while the rental is still in flight, if they want the drill for another 24 hours for instance. To indicate this, a new row is written to the database covering that additional period, and a pointer is left in the original record to say "this one modified me". The result is something like this:
pk custId prodId overrideByPk startDate endDate
----------------------------------------------------------
1 1 1 0 1-1-2000 2-1-2000
2 1 1 3 1-2-2000 2-2-2000
3 1 1 4 3-2-2000 4-2-2000
4 1 1 0 4-2-2000 5-2-2000
These records represent two rental terms. The first ran for a single day in January, and the second ran from the 1st to the 5th of February. My goal is to produce output like this…
pk custId prodId startDate endDate
--------------------------------------------
1 1 1 1-1-2000 2-1-2000
2 1 1 1-2-2000 5-2-2000
It seems, based on the data I've looked at so far, that a record with a overrideByPk=0
is the last record in a string, even in a string of one row. Note that my example has separate date periods, but that's only for clarity. The customer may indeed return the item and the pick it back up the same day, so you can't look for discontinuities in the dates.
I can do this in C# code by getting all the rows with zero, and then looking for those overrideByPk
's repeatedly, but there are thousands of these and I am concerned about performance and code complexity. I seem to recall solving this in SQL in the past, but can no longer remember the trick (if it existed).
Best Answer
If you are using SQL 2012 as your tag indicates, then you can do this with a recursive CTE, although it's a little different since you find the child first and then the parents. But Take a look at the sample below.
The Setup
The Query