sql - How to select the TOP 1 record per group (Partition) -
i've got table called tblroutes holds unique list of , routes (f = from; t = to):
| fcity | fstate | tcity | tstate | |========|========|========|========| |new york| ny | miami | ca | |houston | tx |new york| ny | ...
and have table called tblcarrierrates lists bunch of tiers , rates offered carriers travelling routes:
| fcity | fstate | tcity | tstate | tier | rate | carrid | carrname | |========|========|========|========|======|======|========|=============| |new york| ny | miami | ca | 2 | $2.99| abcd | abracadabra | |new york| ny | miami | ca | 1 | $3.00| bump | bumpy rides | |houston | tx |new york| ny | 2 | $4.00| slow |slow carriers| |houston | tx |new york| ny | 2 | $4.01| abcd | abracadabra | ...
for each unique route listed in tblroutes i'm looking 1 "best" offered tblcarrierrates.
the criteria "the best" lowest tier, followed lowest rate.
the result needs return fields shown in tblcarrierrates, based on 2 routes shown above in tblroutes, desired result be:
| fcity | fstate | tcity | tstate | tier | rate | carrid | carrname | |========|========|========|========|======|======|========|=============| |new york| ny | miami | ca | 1 | $3.00| bump | bumpy rides | |houston | tx |new york| ny | 2 | $4.00| slow |slow carriers|
the approach looking @ sort in ascending order tier , rate, how match top 1 record each unique combination of fcity, fstate, tcity, , tstate:
select a.fcity, a.fstate, a.tcity, a.tstate, q.tier, q.rate, q.carrid, q.carrname tblroutes left join (select top 1 b.carrid, b.carrname, b.fcity, b.fstate, b.tcity, b.tstate, b.rate, b.tier tblcarrierrates b order tblcarrierrates.tier asc, tblcarrierrates.rate asc) q on (a.tstate = q.tstate) , (a.tcity = q.tcity) , (a.fstate = q.fstate) , (a.fcity = q.fcity);
the query doesn't fail, can guess, subquery i've written (q) returns single record rather 1 each route in tblroutes, end result is:
| fcity | fstate | tcity | tstate | tier | rate | carrid | carrname | |========|========|========|========|======|======|========|=============| |new york| ny | miami | ca | 1 | $3.00| bump | bumpy rides | |houston | tx |new york| ny | | | | |
...as can see, nothing's been matched houston new york because sub query returned 1 result rather 1 each route.
how can achieve result i'm after?
i believe looking equivalent of sql server , oracle analytic / windowing functions row_number() on (partition .. order by)
, e.g. like so.
although isn't directly offered in ms access, believe possible simulate row numbering function in ms access applying correlated subquery counts number of rows have same "partition" (as defined join filter), , in each row ranked counting number of preceding rows in same partition, 'below' ordering criteria:
select a.fcity, a.fstate, a.tcity, a.tstate, q.tier, q.rate, q.carrid, q.carrname, therank tblroutes left join ( select b.carrid, b.carrname, b.fcity, b.fstate, b.tcity, b.tstate, b.rate, b.tier, ( select count(*) + 1 tblcarrierrates rnk -- partition simulation (join) b.fcity = rnk.fcity , b.fstate = rnk.fstate , b.tcity = rnk.tcity , b.tstate = rnk.tstate -- order simulation , (rnk.tier < b.tier or (rnk.tier = b.tier , rnk.rate < b.rate))) therank tblcarrierrates b) q on (a.tstate = q.tstate) , (a.tcity = q.tcity) , (a.fstate = q.fstate) , (a.fcity = q.fcity) -- now, want top rank in each partition. therank = 1;
just forewarned of performance - subquery executed each row. also, if there ties, both rows returned.
the +1 start each partition off row number of 1 (since there 0 preceding rows in partition)
edit, taking out comments
select a.fcity, a.fstate, a.tcity, a.tstate, q.tier, q.rate, q.carrid, q.carrname, therank tblroutes left join ( select b.carrid, b.carrname, b.fcity, b.fstate, b.tcity, b.tstate, b.rate, b.tier, ( select count(*) + 1 tblcarrierrates rnk b.fcity = rnk.fcity , b.fstate = rnk.fstate , b.tcity = rnk.tcity , b.tstate = rnk.tstate , (rnk.tier < b.tier or (rnk.tier = b.tier , rnk.rate < b.rate))) therank tblcarrierrates b) q on (a.tstate = q.tstate) , (a.tcity = q.tcity) , (a.fstate = q.fstate) , (a.fcity = q.fcity) therank = 1
Comments
Post a Comment