Not using MSSQL or DB2 or Oracle. No CTE. No OVERLAP predicate. No INTERVAL data type. The situation: on a vehicle to be repaired work can not start until all parts ordered for the job have been received. Parts may be ordered multiple times prior to the start of repair. We need to extract the time for which the vehicle was on "parts hold"
So for a vehicle identified as id = 1 parts were ordered (d1) and received (d2) on 4 different occasions
ID d1 d2
1 8/1 8/8
1 8/2 8/6
1 8/12 8/14
1 8/3 8/10
8/1 8/8
d1 d2
|-------------------------------|
8/2 8/6 8/12 8/14
d1 d2 d1 d2
|---------------| |----------|
8/3 8/10
d1 d2
|---------------------|
8/1 8/14
|---------------------------------------------------------| = 13 days
8/10 8/12
|--------------------------------------| + |----------| = parts hold = 11 days
As seen from above, the wait time to start work (assuming 8/1 as the date from which the vehicle was available for work) was 13 days. The actual time spent waiting for parts was 11 days, which is the number we need to derive from the data. The actual datetime data will be timestamps from which we will extract hours, we used dates in this sample data for simplicity of presentation. We are struggling to generate a set (not psm, not udf, not cursor) based solution. TIA
I couldn't get @Alex W's queries to work. It is not standard SQL, so it required a lot of rewrite to be compatible with SQL Server (which I can test). But it did give me some inspiration, which I have expanded upon.
Find all start-points of every period of uninterrupted waiting:
And the equivalent for end-points:
n
is the number of days since some common point in time. Start-points have a negative value, and end-points have a positive value. This is so that we can just add them up to get the number of days in between.Finally, we just need to add things up:
Input table (Orders):
Output:
Alternatively, you can do this with a stored procedure.
Call it with:
This SQL statement seems to get what you want (t is the table name of the sampe table):
The outer query gets the duration of the repair work. The complex subquery calculates the total number of days not waiting for parts. This is done by locating the start dates where the vehicle is not waiting for parts, and then count the number of days until it begins to wait for parts again:
// 2) The days where it vehicle is not waiting for part is the date from the above query till the vehicle is // waiting for part again
Combining the two above and aggregating all such periods gives the number of days that the vehicle is not waiting for parts. The final query adds an extra condition to calculate result for each id from the outer query.
This probably is not terribly efficient on very large table with many ids. It should fine if the id is limited to one or just a few.