Search code examples
sqloraclerankdense-rank

How to get top n rows from a dense_rank()


I'm trying to get collect the top customers from each region however I seem to run into the issue of not being able to specify that I want only the top customers.

I keep getting this error: ORA-00904: "RANK_UNITPRICE": invalid identifier and I know its coming from the where statement but I don't know how else to filter to get my expected output.

Here's what my code looks like:

select reg_name, cus_lname, sum(sale_units *  sale_price) as total_sold,
rank() over (partition by reg_name order by sum(sale_units *  sale_price) desc) as rank_unitprice
from dwregion
inner join dwcustomer on dwregion.reg_id = dwcustomer.reg_id
inner join dwsalesfact on dwcustomer.cus_code = dwsalesfact.cus_code
where rank_unitprice = 1
group by reg_name, cus_lname

It works if I take the where statement out the code works fine as expected (correct ranks and correct values) but its unfiltered (obviously).

How would I go about fixing this issue?

I'm using Oracle live and you can find the script here if it helps.


Solution

  • At first I didn't understand what something that you should do ("take the where clause out of code") doesn't work. Then I realized that you probably did it wrong - "out" here means that current query should be a subquery (or a CTE). Something like this:

    WITH
       temp
       AS
          (  SELECT reg_name,
                    cus_lname,
                    SUM (sale_units * sale_price) AS total_sold,
                    RANK ()
                       OVER (PARTITION BY reg_name
                             ORDER BY SUM (sale_units * sale_price) DESC) AS rank_unitprice
               FROM dwregion
                    INNER JOIN dwcustomer ON dwregion.reg_id = dwcustomer.reg_id
                    INNER JOIN dwsalesfact
                       ON dwcustomer.cus_code = dwsalesfact.cus_code
           GROUP BY reg_name, cus_lname)
    SELECT t.*
      FROM temp
     WHERE t.rank_unitprice = 1