This seems like a really simple problem but I can’t seem to figure it out right now…
Here is a simplified view of the data that I am fetching from my current stored proc:
ID Name Class Desc
--- ----- ------ -----
84 Calvin J. 2B
53 Fred D. 3B
53 Fred D. ADJ Change/Correction
47 Mary F. 3A
47 Mary F. ADJ New Product
09 Donald M. ADJ Cancelled
21 Richard G. ADJ Bad Debt
21 Richard G. ADJ Cancelled
I need to modify my procedure to select only one record per individual. If a person has an adjustment, I only want to select the record with the adjustment and disregard the other record. Based on the above, this is the result set that I am trying to return:
ID Name Class Desc
--- ----- ------ -----
84 Calvin J. 2B
53 Fred D. ADJ Change/Correction
47 Mary F. ADJ New Product
09 Donald M. ADJ Cancelled
21 Richard G. ADJ Cancelled
Help please!
UPDATE
I just realized that there is an additional requirement for this query; if there are two adjustments where one has a description of “Bad Debt” and the other “Cancelled”, the record with the “Cancelled” description needs to be selected (see updated data above).
This should do the trick:
It looks scarier than it really is. The inner query contains an extra column computed with
ROW_NUMBER(). What this does is number your rows, starting over at 1 for each distinctID(specified in thePARTITION BY). TheORDER BY, which tellsROW_NUMBER()how to order the rows, is a case statement saying that rows withClass = 'ADJ'should come before all other rows. Then at the end we grab only rows numbered 1. The result is selecting the ADJ row if there is one for thatID, or the regular row otherwise.Edit in response to updated requirements
If you have additional prioritization criteria then you can add those into the
ORDER BY, just like you wouldORDER BYin a regular query. Often it’s helpful to execute just the inner query without filtering down torn = 1so you can see exactly how row numbers are being assigned.Here’s the updated query that should satisfy your new requirement:
See it in action here.