简体   繁体   中英

Using a pl-sql procedure or cursor to select top 3 rank

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
mark            focus   101 250  
mark             focus  101 2500  
mark             focus  101 1000  
mark             focus  101 1500  
henry   520i    21405   500  
henry   520i    21405   100  
henry   520i    21405   750  
henry   520i    21405   100  
mark            taurus  48360   250    
mark            mustang 730 500  
mark            mustang 730 1000  
mark            mustang 730 1250  

Desired Output:

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

Try this....

select * from (
select customer,make,zipcode,offer, dense_rank() over (PARTITION by customer order by customer,make, zipcode,offer desc) Rank from tablename)
where Rank <4;

SQL Fiddle

Oracle 11g R2 Schema Setup :

CREATE TABLE TEST ( customer, make, zipcode, offer ) AS
          SELECT 'mark',  'focus',    101,  250 FROM DUAL
UNION ALL SELECT 'mark',  'focus',    101, 2500 FROM DUAL
UNION ALL SELECT 'mark',  'focus',    101, 1000 FROM DUAL
UNION ALL SELECT 'mark',  'focus',    101, 1500 FROM DUAL
UNION ALL SELECT 'henry', '520i',   21405,  500 FROM DUAL
UNION ALL SELECT 'henry', '520i',   21405,  100 FROM DUAL
UNION ALL SELECT 'henry', '520i',   21405,  750 FROM DUAL
UNION ALL SELECT 'henry', '520i',   21405,  100 FROM DUAL
UNION ALL SELECT 'mark',  'taurus', 48360,  250 FROM DUAL
UNION ALL SELECT 'mark',  'mustang',  730,  500 FROM DUAL
UNION ALL SELECT 'mark',  'mustang',  730, 1000 FROM DUAL
UNION ALL SELECT 'mark',  'mustang',  730, 1250 FROM DUAL;

Query 1 - If you want at most 3 rows per group: :

WITH ranks AS (
  SELECT t.*,
         ROW_NUMBER() OVER ( PARTITION BY CUSTOMER, MAKE, ZIPCODE ORDER BY OFFER DESC ) AS RANK
  FROM   TEST t
)
SELECT *
FROM   RANKS
WHERE  RANK <= 3

Results :

| CUSTOMER |    MAKE | ZIPCODE | OFFER | RANK |
|----------|---------|---------|-------|------|
|    henry |    520i |   21405 |   750 |    1 |
|    henry |    520i |   21405 |   500 |    2 |
|    henry |    520i |   21405 |   100 |    3 |
|     mark |   focus |     101 |  2500 |    1 |
|     mark |   focus |     101 |  1500 |    2 |
|     mark |   focus |     101 |  1000 |    3 |
|     mark | mustang |     730 |  1250 |    1 |
|     mark | mustang |     730 |  1000 |    2 |
|     mark | mustang |     730 |   500 |    3 |
|     mark |  taurus |   48360 |   250 |    1 |

Query 2 - If you want the top 3 ranks including ties :

WITH ranks AS (
  SELECT t.*,
         DENSE_RANK() OVER ( PARTITION BY CUSTOMER, MAKE, ZIPCODE ORDER BY OFFER DESC ) AS RANK
  FROM   TEST t
)
SELECT *
FROM   RANKS
WHERE  RANK <= 3

Results :

| CUSTOMER |    MAKE | ZIPCODE | OFFER | RANK |
|----------|---------|---------|-------|------|
|    henry |    520i |   21405 |   750 |    1 |
|    henry |    520i |   21405 |   500 |    2 |
|    henry |    520i |   21405 |   100 |    3 |
|    henry |    520i |   21405 |   100 |    3 |
|     mark |   focus |     101 |  2500 |    1 |
|     mark |   focus |     101 |  1500 |    2 |
|     mark |   focus |     101 |  1000 |    3 |
|     mark | mustang |     730 |  1250 |    1 |
|     mark | mustang |     730 |  1000 |    2 |
|     mark | mustang |     730 |   500 |    3 |
|     mark |  taurus |   48360 |   250 |    1 |

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM