Question

I have a table giving ratings for various suppliers/areas. The format is below.

I would like to know, for each distinct month, and supplier (exp_id)

What was the highest and lowest rated pickup_ward_text

My expected output is similar to:

[year][month][exp_id] [highest rated pickup_ward] [lowest rated pickup_ward]

Where the 'rated' is an average of rating_driver, rating_punctuality & rating_vehicle

I am completely lost on how to achieve this, I have tried to past the first line of the table correctly below. a

Year    Month   exp_id  RATING_DRIVER   RATING_PUNCTUALITY  RATING_VEHICLE  booking_id  pickup_date ratingjobref    rating_date PICKUP_WARD_TEXT
2013       10    4            5.00       5.00                      5.00     1559912    30:00.0    1559912       12/10/2013 18:29       N4
Was it helpful?

Solution

There's a common pattern using row_number() to find either the minimum or the maximum. You can combine them with a little trickery:

select
    year,
    month,
    exp_id,
    max(case rn1 when 1 then pickup_ward_text end) as min_pickup_ward_text,
    max(case rn2 when 1 then pickup_ward_text end) as max_pickup_ward_text
from (
    select
        year,
        month,
        exp_id,
        pickup_ward_text,
        row_number() over (
            partition by year, month, exp_id 
            order By rating_driver + rating_punctuality + rating_vehicle
        ) rn1,
        row_number() over (
            partition by year, month, exp_id 
            order By rating_driver + rating_punctuality + rating_vehicle desc
        ) rn2
    from
        mytable
    ) x
where
    rn1 = 1 or rn2 = 1 -- this line isn't necessary, but might make things quicker
group by
    year,
    month,
    exp_id
order by
    year,
    month,
    exp_id

It may actually be faster to do two derived tables, for each part and inner join them. Some testing is in order:

select
    n.year,
    n.month,
    n.exp_id,
    n.pickup_ward_text as min_pickup_ward_text,
    x.pickup_ward_text as max_pickup_ward_text
from (
    select
        year,
        month,
        exp_id,
        pickup_ward_text,
        row_number() over (
            partition by year, month, exp_id 
            order By rating_driver + rating_punctuality + rating_vehicle
        ) rn
    from
        mytable
    ) n
    inner join (
    select
        year,
        month,
        exp_id,
        pickup_ward_text,
        row_number() over (
            partition by year, month, exp_id 
            order By rating_driver + rating_punctuality + rating_vehicle desc
        ) rn
    from
        mytable
    ) x
    on n.year = x.year and n.month = x.month and n.exp_id = x.exp_id
where
    n.rn = 1 and
    x.rn = 1 
order by
    year,
    month,
    exp_id
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top