Author |
Topic |
LaurieCox
158 Posts |
Posted - 2012-03-30 : 12:08:06
|
I have a table that stores drug prescription history. I thought I could see the history of given patient/drug by sorting the table by member_id, drug_name, orderhistory and ordercontent. But that turned out not to be the case for reasons that don't need exploring at this juncture.Anyway within each member_id/Drug_name pairing I have to sort via a couple of "linking fields" (instead of orderhistory/ordercontent).So here is the table:CREATE TABLE #RxHistory ( NumDosages int, member_id int, Drug_Name varchar(50), orderhistory_id int, ordercontent_id int, srcrx_id int, rx_id int, event varchar(10), rx_dosage_id int) The fields to create the linking are the srcrx_id and rx_id fields. The srcrx_id points to the rx_id of the record it should follow in the sort. There are two possibilities if srcrx_id = rx_id:- Event = Active - first record in chain
- Event = Discontinu – last record in chain*
*A Chain might not end on Discontinu but if it ends on Reorder or Change the srcrx_id will not equal the rx_id. There is a twist: One member/drug/event can have multiple records (for different dosages). These records should always be grouped together and their order doesn't matter. These records will have the same srcrx_id and rx_id. With the srcrx_id pointing to the rx_id of the record(s) each should follow. The NumDosages field tells how many records are in these groups.So they say a picture is worth a thousand words, so maybe a color coded table might help.Here is the data sorted by member_id, drug_name, orderhistory and ordercontent. But I want the data sorted so that each color group is sorted together (data dml at end of post):NumDosages member_id Drug_Name orderhistory_id ordercontent_id srcrx_id rx_id event rx_dosage_id----------- ----------- --------------- --------------- --------------- ----------- ----------- ---------- ------------2 2202716 Adderall 5701362 11190879 10211987 10211987 Active 113449742 2202716 Adderall 5701362 11190879 10211987 10211987 Active 113449752 2202716 Adderall 5940275 11647794 10211987 10628922 Change 117963322 2202716 Adderall 5940275 11647794 10211987 10628922 Change 117963311 2202716 Adderall 6033829 11824592 10628922 10791589 Change 119724812 2202716 Adderall 6137645 12021262 10972692 10972692 Active 121684742 2202716 Adderall 6137645 12021262 10972692 10972692 Active 121684751 2202716 Adderall 6137653 12021273 10791589 10791589 Discontinu 119724811 2202716 Adderall 6137754 12021459 10972692 10972868 Change 121686641 2202716 Adderall 6137763 12021474 10972882 10972882 Active 121686801 2202716 Adderall 6388818 12494000 10972868 11405646 Change 126375911 2202716 Adderall 6388861 12494082 10972882 11405719 Reorder 126376761 2202716 Adderall 6742841 13160076 11405646 11405646 Discontinu 12637591 Explanation of why the red are grouped as shown:The first two rows are one of the multiple groupings (i.e. two dosages for one member/drug/event). They are also the first record(s) in a set as srcrx_id = rx_id and event = 'Active'. The next two records are also a group and they follow the first two records as their srcrx_id (10211987) = the rx_id in the first two records. The next time the drug was prescribed they dropped one of the dosages which is why there is only one record that points to the previous multi record group. The last record in the "red" chain is the 8th record above as its srcrx_id (10791589) points to to the rx_id of the 5th record.So given the table above my expected results should be:NumDosages member_id Drug_Name orderhistory_id ordercontent_id srcrx_id rx_id event rx_dosage_id----------- ----------- --------------- --------------- --------------- ----------- ----------- ---------- ------------2 2202716 Adderall 5701362 11190879 10211987 10211987 Active 113449742 2202716 Adderall 5701362 11190879 10211987 10211987 Active 113449752 2202716 Adderall 5940275 11647794 10211987 10628922 Change 117963322 2202716 Adderall 5940275 11647794 10211987 10628922 Change 117963311 2202716 Adderall 6033829 11824592 10628922 10791589 Change 119724811 2202716 Adderall 6137653 12021273 10791589 10791589 Discontinu 119724812 2202716 Adderall 6137645 12021262 10972692 10972692 Active 121684742 2202716 Adderall 6137645 12021262 10972692 10972692 Active 121684751 2202716 Adderall 6137754 12021459 10972692 10972868 Change 121686641 2202716 Adderall 6388818 12494000 10972868 11405646 Change 126375911 2202716 Adderall 6742841 13160076 11405646 11405646 Discontinu 126375911 2202716 Adderall 6137763 12021474 10972882 10972882 Active 121686801 2202716 Adderall 6388861 12494082 10972882 11405719 Reorder 12637676 Note that the "blue" group does not end on a Discontinue event.I don't think I really care what order the "color groups" are in for given member_id/drug_name set of records. I.e. the records above could be ordered green/blue/red and I wouldn't care. Though I suppose it would be nice if the color grouping with the smallest first rx_id came first in the sort. I have been reading about recursive common table expressions where I think my solution lies, but I am having trouble understanding how they work and how to apply them to this problem. I think the multiple records for a given member/drug/event and the way the beginning (srcrx_id = rx_id and event = Active) and (possible) ending (srcrx_id = rx_id and event = Discontinu) of the "chains" are setup make the solution more complicated than the usual hierarchical solution examples I have seen so far in my reading.Thanks,LaurieTest data for example given:INSERT INTO #RxHistorySELECT 2,2202716,'Adderall',5701362,11190879,10211987,10211987,'Active',11344974 UNION ALLSELECT 2,2202716,'Adderall',5701362,11190879,10211987,10211987,'Active',11344975 UNION ALLSELECT 2,2202716,'Adderall',5940275,11647794,10211987,10628922,'Change',11796332 UNION ALLSELECT 2,2202716,'Adderall',5940275,11647794,10211987,10628922,'Change',11796331 UNION ALLSELECT 1,2202716,'Adderall',6033829,11824592,10628922,10791589,'Change',11972481 UNION ALLSELECT 2,2202716,'Adderall',6137645,12021262,10972692,10972692,'Active',12168474 UNION ALLSELECT 2,2202716,'Adderall',6137645,12021262,10972692,10972692,'Active',12168475 UNION ALLSELECT 1,2202716,'Adderall',6137653,12021273,10791589,10791589,'Discontinu',11972481 UNION ALLSELECT 1,2202716,'Adderall',6137754,12021459,10972692,10972868,'Change',12168664 UNION ALLSELECT 1,2202716,'Adderall',6137763,12021474,10972882,10972882,'Active',12168680 UNION ALLSELECT 1,2202716,'Adderall',6388818,12494000,10972868,11405646,'Change',12637591 UNION ALLSELECT 1,2202716,'Adderall',6388861,12494082,10972882,11405719,'Reorder',12637676 UNION ALLSELECT 1,2202716,'Adderall',6742841,13160076,11405646,11405646,'Discontinu',12637591 --additional test dataINSERT INTO #RxHistorySELECT 2,1161600,'Geodon',7544749,14665602,13392220,13392220,'Active',14789322 UNION ALLSELECT 2,1161600,'Geodon',7544749,14665602,13392220,13392220,'Active',14789321 UNION ALLSELECT 1,1161600,'Geodon',7732911,15019409,13715110,13715110,'Active',15138164 UNION ALLSELECT 2,1161600,'Geodon',7732911,15019411,13392220,13392220,'Discontinu',14789322 UNION ALLSELECT 2,1161600,'Geodon',7732911,15019411,13392220,13392220,'Discontinu',14789321 UNION ALLSELECT 1,1161600,'Geodon',7929106,15390853,13715110,14054760,'Reorder',15505132 UNION ALLSELECT 1,1161600,'Geodon',8094520,15704031,14054760,14340808,'Reorder',15814169 UNION ALLSELECT 1,1161600,'Geodon',8979570,17398166,14340808,15889402,'Reorder',17482104 UNION ALLSELECT 1,1161600,'Geodon',9425431,18242925,15889402,16661267,'Reorder',18310160 UNION ALLSELECT 1,1161600,'Geodon',9752837,18868647,16661267,17235140,'Reorder',18925047 UNION ALLSELECT 1,1161600,'Ativan',6901411,13458977,12288560,12288560,'Active',13594431 UNION ALLSELECT 1,1161600,'Ativan',6997730,13639554,12288560,12454409,'Reorder',13774209 UNION ALLSELECT 1,1161600,'Ativan',7084079,13801775,12454409,12603558,'Change',13935715 UNION ALLSELECT 1,1161600,'Ativan',7544749,14665599,12603558,13392217,'Reorder',14789318 UNION ALLSELECT 1,1161600,'Ativan',9425469,18242997,13392217,16661332,'Reorder',18310231 UNION ALLSELECT 2,1245979,'Depakote',5246797,10328838,9427751,9427751,'Active',10494363 UNION ALLSELECT 2,1245979,'Depakote',5246797,10328838,9427751,9427751,'Active',10494362 UNION ALLSELECT 2,1245979,'Depakote',5367492,10558633,9427751,9636747,'Reorder',10721193 UNION ALLSELECT 2,1245979,'Depakote',5367492,10558633,9427751,9636747,'Reorder',10721192 UNION ALLSELECT 1,1245979,'Depakote',5423878,10665776,9733943,9733943,'Active',10826606 UNION ALLSELECT 1,1245979,'Depakote',5448264,10711872,9733943,9733943,'Discontinu',10826606 UNION ALLSELECT 2,1245979,'Depakote',5538441,10881088,9636747,9929767,'Reorder',11038935 UNION ALLSELECT 2,1245979,'Depakote',5538441,10881088,9636747,9929767,'Reorder',11038934 UNION ALLSELECT 2,1245979,'Depakote',5674794,11140347,9929767,10165950,'Reorder',11295158 UNION ALLSELECT 2,1245979,'Depakote',5674794,11140347,9929767,10165950,'Reorder',11295159 UNION ALLSELECT 2,1245979,'Depakote',5915166,11599312,10165950,10584817,'Reorder',11748614 UNION ALLSELECT 2,1245979,'Depakote',5915166,11599312,10165950,10584817,'Reorder',11748615 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749909 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749907 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749908 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749908 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749909 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749907 |
|
X002548
Not Just a Number
15586 Posts |
|
LaurieCox
158 Posts |
Posted - 2012-03-30 : 14:33:59
|
Yeah I was afraid of that.Not sure as I can be simpler but I can try to describe it better.I want to sort a table so that the data is sorted by member_id, drug_name and the records within each given member_id/drug_name are arranged (sorted) according to how they link via the srcrx_id and rx_id.First I will remove ordercontent_id and orderhistory_id from my example table as they do not have anything to do with the solution and number the rows to use for reference. So here is the tableRow NumDosages member_id Drug_Name srcrx_id rx_id event rx_dosage_id--- ----------- ----------- ------------ ----------- ----------- ---------- ------------1 2 2202716 Adderall 10211987 10211987 Active 113449742 2 2202716 Adderall 10211987 10211987 Active 113449753 2 2202716 Adderall 10211987 10628922 Change 117963324 2 2202716 Adderall 10211987 10628922 Change 117963315 1 2202716 Adderall 10628922 10791589 Change 119724816 2 2202716 Adderall 10972692 10972692 Active 121684747 2 2202716 Adderall 10972692 10972692 Active 121684758 1 2202716 Adderall 10791589 10791589 Discontinu 119724819 1 2202716 Adderall 10972692 10972868 Change 1216866410 1 2202716 Adderall 10972882 10972882 Active 1216868011 1 2202716 Adderall 10972868 11405646 Change 1263759112 1 2202716 Adderall 10972882 11405719 Reorder 1263767613 1 2202716 Adderall 11405646 11405646 Discontinu 12637591 I will start with the "blue" chain as it is the easiest. The first record in the blue chain is row 10. We know this is a first record in a chain because srcrx_id = rx_id and event = Active. The second record in the blue chain is row 12. We know this row should follow row 10 because its srcrx_id = the rx_id of row 10.There is nothing about this record that tells us it’s at the end of a chain but we know it is because there is no other record whose srcrx_id = row 12's rx_id. So the blue chain is only two records long and should sort together.Now I will do the green chain:The green chain has two records as the beginning of the chain (rows 6 and 7). This is the part I tried to explain in the "There is a twist:" section in my op. These records represent a single script that was written for two different dosages. You can tell that these are a single script as the only difference between the two records is the rx_dosage_id (all other fields are equal).You can tell these are the beginning of a chain because srcrx_id = rx_id and event = Active for each record.The next record in the green chain is row 9. Note that there is only one dosage record that follows rows 6 and 7. This is because one of the two dosages was dropped. You can tell that this record follows rows 6 and 7 because the row 9's srcrx_id = the rx_id of rows 6 and 7.Row 11 is next in the green chain because row 11's srcrx_id = row 9's rx_id.Row 13 is next because row 13's srcrx_id = row 11's rx_id.Row 13 is the last in the green chain because srcrx_id = rx_id and event = 'Discontinu', also there will be no other record whose srcrx_id = 13's rx_id.So I hope that is as clear as mud. I will post more examples on Monday if I don't get any solutions.I am also trying to solve this myself by reading about recursive common table expressions where I think the solution lies. Thanks,Laurie |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2012-03-30 : 14:38:59
|
this was a pain:) Next time, just have a column that groups it so you don't need to be as creative on the sort query!Here you go:drop table #tmp1,#RxHistory,#FInaltmpCREATE TABLE #RxHistory ( NumDosages int, member_id int, Drug_Name varchar(50), orderhistory_id int, ordercontent_id int, srcrx_id int, rx_id int, event varchar(10), rx_dosage_id int)insert into #RxHistorySELECT 2,1161600,'Geodon',7544749,14665602,13392220,13392220,'Active',14789322 UNION ALLSELECT 2,1161600,'Geodon',7544749,14665602,13392220,13392220,'Active',14789321 UNION ALLSELECT 1,1161600,'Geodon',7732911,15019409,13715110,13715110,'Active',15138164 UNION ALLSELECT 2,1161600,'Geodon',7732911,15019411,13392220,13392220,'Discontinu',14789322 UNION ALLSELECT 2,1161600,'Geodon',7732911,15019411,13392220,13392220,'Discontinu',14789321 UNION ALLSELECT 1,1161600,'Geodon',7929106,15390853,13715110,14054760,'Reorder',15505132 UNION ALLSELECT 1,1161600,'Geodon',8094520,15704031,14054760,14340808,'Reorder',15814169 UNION ALLSELECT 1,1161600,'Geodon',8979570,17398166,14340808,15889402,'Reorder',17482104 UNION ALLSELECT 1,1161600,'Geodon',9425431,18242925,15889402,16661267,'Reorder',18310160 UNION ALLSELECT 1,1161600,'Geodon',9752837,18868647,16661267,17235140,'Reorder',18925047 UNION ALLSELECT 1,1161600,'Ativan',6901411,13458977,12288560,12288560,'Active',13594431 UNION ALLSELECT 1,1161600,'Ativan',6997730,13639554,12288560,12454409,'Reorder',13774209 UNION ALLSELECT 1,1161600,'Ativan',7084079,13801775,12454409,12603558,'Change',13935715 UNION ALLSELECT 1,1161600,'Ativan',7544749,14665599,12603558,13392217,'Reorder',14789318 UNION ALLSELECT 1,1161600,'Ativan',9425469,18242997,13392217,16661332,'Reorder',18310231 UNION ALLSELECT 2,1245979,'Depakote',5246797,10328838,9427751,9427751,'Active',10494363 UNION ALLSELECT 2,1245979,'Depakote',5246797,10328838,9427751,9427751,'Active',10494362 UNION ALLSELECT 2,1245979,'Depakote',5367492,10558633,9427751,9636747,'Reorder',10721193 UNION ALLSELECT 2,1245979,'Depakote',5367492,10558633,9427751,9636747,'Reorder',10721192 UNION ALLSELECT 1,1245979,'Depakote',5423878,10665776,9733943,9733943,'Active',10826606 UNION ALLSELECT 1,1245979,'Depakote',5448264,10711872,9733943,9733943,'Discontinu',10826606 UNION ALLSELECT 2,1245979,'Depakote',5538441,10881088,9636747,9929767,'Reorder',11038935 UNION ALLSELECT 2,1245979,'Depakote',5538441,10881088,9636747,9929767,'Reorder',11038934 UNION ALLSELECT 2,1245979,'Depakote',5674794,11140347,9929767,10165950,'Reorder',11295158 UNION ALLSELECT 2,1245979,'Depakote',5674794,11140347,9929767,10165950,'Reorder',11295159 UNION ALLSELECT 2,1245979,'Depakote',5915166,11599312,10165950,10584817,'Reorder',11748614 UNION ALLSELECT 2,1245979,'Depakote',5915166,11599312,10165950,10584817,'Reorder',11748615 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749909 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749907 UNION ALLSELECT 3,1245979,'Depakote',6449491,12607778,10584817,11509401,'Change',12749908 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749908 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749909 UNION ALLSELECT 3,1245979,'Depakote',6963168,13574815,11509401,11509401,'Discontinu',12749907select row_number() over (order by (select 1)) as rowid,*into #TMP1from#RxHistoryorder by srcrx_ID;with cte( rowid, NumDosages, member_id , Drug_Name , orderhistory_id , ordercontent_id , srcrx_id , rx_id , event, rx_dosage_id,sort)as(select * ,'-' + cast(rowid as varchar(max)) + '-'from#TMP1where rx_id = srcrx_idand event = 'Active'union allselect b.* ,a.sort + '-' + cast(b.rowid as varchar(max)) + '-'from#TMP1 binner joincte aon a.member_id = b.member_idand( b.srcrx_id = a.srcrx_id or b.srcrx_id = a.rx_id or b.rx_id = a.srcrx_id or b.rx_id = a.rx_id)where b.rowid > a.rowid)select * into #FInaltmpfrom cteOPTION (MAXRECURSION 0)select *from #TMP1 across apply(select top 1 aa.sort from #Finaltmp aa where aa.sort like '%-' + cast(a.rowid as varchar(10)) + '-%' order by len(aa.sort) desc) border by member_id,b.sort,event,rx_id Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
LaurieCox
158 Posts |
Posted - 2012-03-30 : 15:22:28
|
Hi Vinnie,First of all thank you for all your work. I chuckled at your "next time … comment". Oh that I could have nice easy data to work with. The data is not mine I am just trying to work with it. This is actually step x in a process to take this data and convert it to another system (whose table structure I also have no control over). Anyway I am sorry to report that your solution breaks down when I add the other sample data (in my op) to the RxHistory table. I haven't started analyzing it yet so I don't know why.Anyway you have given me something to work with (so thank you for that). Probably won't have finished analyzing your solution before the end of the work day so I won't get back with a better response then "it don't work" until Monday. One thing I notice at first glance is that the Adderall records are scattered willy-nilly throughout the result set. The other records (except for the intrusion of Adderall) look like they are at least grouped correctly by member_id/drug_name. I haven't looked at if they order by linked data correctly.One thing missing from my test data is records for the same drug but different members (if these were there they should sort as completely different groups). The test data does include a member_id (1161600) with more than one drug though.But again, thank you for your work. I really do appreciate it.Laurie |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2012-03-30 : 15:36:24
|
Did you try it since the last edit, I think I corrected that? Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
LaurieCox
158 Posts |
Posted - 2012-03-30 : 15:47:03
|
Hi Vinnie,Yep, at a glance the results look much better. By the way I looked it up and Adderall is a drug used to help treat ADHD. I thought maybe that was why the Adderall records were scattered willy-nilly throughout the result set.Again thank you very much,Laurie |
 |
|
Vinnie881
Master Smack Fu Yak Hacker
1231 Posts |
Posted - 2012-03-30 : 16:01:03
|
Welcome, since it is not your data you are working with, tell the people that created it that their data structure sucks to work with;)With some index's and a few minor changes, you should be able to improve the query quite a bit.I'd also change it into a table-valued function and pass the member_id/drug for better results by filtering the table and issolate the members data into a smaller set so the join that uses all the OR's do not cripple performance.Select * fromMemberDrugtable a --A table that has the unique members and drug type information.cross applyfn_getorderedresults(a.member_id, a.Drug_Name) this should hopefully allow for more flexibility and better performance. Success is 10% Intelligence, 70% Determination, and 22% Stupidity.\_/ _/ _/\_/ _/\_/ _/ _/- 881 |
 |
|
|
|
|