Top 2 offers with sum of all offers

2019-09-19 23:01发布

问题:

Can someone please tell how can I get the results as below.

Using dense_rank function where rank <=2 will give me top 2 offers.

I am also looking to get 'total_offer' which should be sum of 'offer1' and 'offer2'. when there is no offer2 ( eg:taurus) 'total offer' should be 'offer1' and 'null' for 'offer2'

Input:

customer    make    zipcode offer notes  
mark        focus   101     250   cash  
mark        focus   101     2500  appreciation cash  
mark        focus   101     1000  cash  
mark        focus   101     1500  cash offer  

henry       520i    21405   500  cash offer  
henry       520i    21405   100  cash  
henry       520i    21405   750  appreciation cash  
henry       520i    21405   100  cash  

mark        taurus  48360   250    appreciation cash  

mark        mustang 730     500  cash  
mark        mustang 730     1000  Cash offer  
mark        mustang 730     1250  appreciation cash  

Desired Output:

| CUSTOMER | MAKE    | ZIPCODE | TOP_OFFER1 | notes1 | TOP_OFFER2 | notes2 | Total_offer |  
| henry | 520i | 21405 | 750  | appreciation cash | 500 | cash offer | 1250    
| mark  | focus   | 101  2500 | appreciation cash | 1500 | cash offer | 4000  
| mark | mustang | 730 | 1250 | appreciation cash | 1000 | cash offer | 2250    
| mark  | taurus  | 48360 | 250 | appreciation cash | NULL       | 250 |   

Thanks

PS:

The link below tells me that dense_rank need to be performed to get top 2 offers. (Using a pl-sql procedure or cursor to select top 3 rank)

回答1:

 with x as 
 (select row_number() over(partition by customer,make order by offer desc) rn,
  customer, make, zipcode, offer from tablename)
 , y as (select customer, make, zipcode, offer from x where rn <=2)
 , z as (select customer, make, zipcode, 
         case when rn = 1 then offer else 0 end as offer_1, 
         case when rn = 2 then offer else 0 end as offer_2 
         from y)
  select customer, make, zipcode, offer_1, offer_2, offer_1+offer_2 total_offer
  from z

This makes use of recursive cte's to accomplish your task.



回答2:

Try this code...

WITH subqueryfactoring AS
  (SELECT customer,
    make ,
    zipcode ,
    offer,
    lead(offer) over (partition BY customer, make , zipcode order by offer DESC) SecondLeadValue,
    row_number() over (partition BY customer, make , zipcode order by offer DESC ) rownumber
  FROM abc1
  )
SELECT customer,
  make ,
  zipcode,
  offer "Top Offer1 ",
  SecondLeadValue "Top offer 2",
  offer + COALESCE(SecondLeadValue,0) "Total Offer"
FROM subqueryfactoring
WHERE rownumber<2;


回答3:

You better use ROW_NUMBER instead of DENSE_RANK (which might return more than two rows) plus a LEAD to find the 2nd highest value

select customer, make, zipcode,
    TOP_OFFER1, 
    TOP_OFFER2, 
    TOP_OFFER1 + coalesce(TOP_OFFER2,0) as Total_offer
from
 ( 
   select customer, make, zipcode, 
      offer as TOP_OFFER1, -- max offer
      lead(offer) over (partition by customer, make, zipped
                        order by offer desc) as TOP_OFFER2, -- 2nd highest offer
      row_number() over (partition by customer, make, zipped
                        order by offer desc) as rn
  from tab
 ) dt
where rn = 1 -- only the row with the highest offer