sql - Getting logically-corresponding records where no direct association exists -


i have table logging requests , responses cases, , times each occurs. problem there no direct association between particular response , request it's responding to. make matters more difficult, there might multiple responses 1 request, , requests , responses aren't collated - might have 2 requests followed 2 responses, means first response relates first request, , second response relates second request. simplified table below gives examples of each of situations:

case_id     subject     date 123         request     2014-12-03 15:48:02 123         response    2014-12-03 16:01:45 123         response    2014-12-03 17:32:23 123         request     2015-04-10 12:12:17 123         request     2015-04-10 12:13:34 123         response    2015-04-10 13:31:20 123         response    2014-04-10 13:37:12 234         request     2014-12-03 12:12:20 234         response    2014-12-03 12:20:23 234         request     2015-03-03 15:09:44 234         response    2015-03-03 16:23:54 

what want find first response corresponds each request within case calculate time took respond. output of query should be:

case_id     request time            response time 123         2014-12-03 15:48:02     2014-12-03 16:01:45 123         2015-04-10 12:12:17     2015-04-10 13:31:20 123         2015-04-10 12:13:34     2015-04-10 13:37:12 234         2014-12-03 12:12:20     2014-12-03 12:20:23 234         2015-03-03 15:09:44     2015-03-03 16:23:54 

the problem i'm having non-collated examples have 2 (or more) requests followed 2 (or more) responses. far i've got this:

select n1.case_id, n1.date request_date, n2.date response_date notes n1   join notes n2     on n1.subject = 'request'     , n2.date = (       select min(date)       notes       case_id = n1.case_id         , subject = 'response'         , date > n1.date     ) 

which works, can see sql fiddle here fails when have multiple requests followed multiple responses - takes first response regardless of fact it's been "claimed" previous request. i've searched around, cannot figure out how make exclude responses have been joined previously.

this unpleasant, seems work data. had fix small glitch in data have different value row #7 in data shown in results.

declare @data table (     case_id int,     [subject] varchar(50),     [date] datetime); insert @data select 123, 'request', '2014-12-03 15:48:02'; insert @data select 123, 'response', '2014-12-03 16:01:45'; insert @data select 123, 'response', '2014-12-03 17:32:23'; insert @data select 123, 'request', '2015-04-10 12:12:17'; insert @data select 123, 'request', '2015-04-10 12:13:34'; insert @data select 123, 'response', '2015-04-10 13:31:20'; insert @data select 123, 'response', '2015-04-10 13:37:12'; insert @data select 234, 'request', '2014-12-03 12:12:20'; insert @data select 234, 'response', '2014-12-03 12:20:23'; insert @data select 234, 'request', '2015-03-03 15:09:44'; insert @data select 234, 'response', '2015-03-03 16:23:54'; rowids (     select         *,         row_number() on (order case_id, [date]) rowid             @data), requests (     select         case_id,         [date]             @data             [subject] = 'request'), nextresponse (     select         r.case_id,         r.[date] request_time,         min(d.[date]) response_time             requests r         inner join @data d on d.case_id = r.case_id , d.[subject] = 'response' , d.[date] > r.[date]     group         r.case_id,         r.[date]), assignids (     select         nr.*,         r.rowid             nextresponse nr         inner join rowids r on r.case_id = nr.case_id , r.[subject] = 'response' , r.[date] = nr.response_time), findduplicates (     select         rowid             assignids     group         rowid     having         count(*) > 1), applyduplicateoffsets (     select         a.case_id,         a.request_time,         a.response_time,         a.rowid,         row_number() on (partition a.rowid order a.response_time) offset             findduplicates fd         inner join assignids on a.rowid = fd.rowid), fixduplicates (     select         a.case_id,         a.request_time,         min(case when d.rowid null a.response_time else a2.[date] end) response_time             assignids         left join findduplicates d on d.rowid = a.rowid         left join applyduplicateoffsets o on o.rowid = a.rowid , o.request_time = a.request_time         left join rowids a2 on a2.case_id = a.case_id , a2.rowid >= a.rowid + o.offset - 1     group         a.case_id,         a.request_time) select     *     fixduplicates order     case_id,     request_time; 

basically works follows:

  • first make list of data unique row id assigned each row;
  • next perform simple match, picking next response each request;
  • this ends using same response multiple rows find happens;
  • next create order duplicates, ordered date, first duplicate assigned 1, 2, etc.;
  • now can reassign response dates (assuming each request has it's own response) picking original response first duplicate, next available response second duplicate, etc.;
  • finally spew out results.

results this:

case_id request_time    response_time 123 2014-12-03 15:48:02.000 2014-12-03 16:01:45.000 123 2015-04-10 12:12:17.000 2015-04-10 13:31:20.000 123 2015-04-10 12:13:34.000 2015-04-10 13:37:12.000 234 2014-12-03 12:12:20.000 2014-12-03 12:20:23.000 234 2015-03-03 15:09:44.000 2015-03-03 16:23:54.000 

is solution? not really, thought need form of recursion , maybe better way solve problem?


Comments

Popular posts from this blog

android - MPAndroidChart - How to add Annotations or images to the chart -

javascript - Add class to another page attribute using URL id - Jquery -

firefox - Where is 'webgl.osmesalib' parameter? -