如何从每个组中选择底部N行 - Oracle 11g

时间:2015-07-13 05:48:37

标签: sql oracle oracle11g greatest-n-per-group

我有一张表格如下:

+-----------------+----------+-------------+-------------+
| QCD_OUTLET_CODE | QCD_YEAR | QCD_QUARTER | QCD_CREDITS |
+-----------------+----------+-------------+-------------+
|       144034911 |     2015 | Q2          | 269.5       |
|        10500106 |     2015 | Q2          | 303.35      |
|       144034911 |     2015 | Q1          | 231.85      |
|        10500106 |     2015 | Q1          | 250.4       |
|        10500106 |     2014 | Q4          | 276.5       |
|       144034911 |     2014 | Q4          | 224.5       |
+-----------------+----------+-------------+-------------+

我需要显示由QCD_YEARQCD_QUARTER排序的底部2行,以便最新的季度具有最后一个等级(显示为每个组的最后一行) 以前,当只有2014/Q42015/Q1时(即每QCD_OUTLET_CODE有两个记录),以下查询可以正常显示我希望的顺序:

WITH ordered 
     AS (SELECT qcd_outlet_code, 
                qcd_year, 
                qcd_quarter, 
                qcd_credit, 
                Row_number() 
                  over ( 
                    PARTITION BY qcd_outlet_code 
                    ORDER BY qcd_outlet_code, qcd_year, qcd_quarter) 
                AS rn 
         FROM   QTR_CREDIT_DATA) 
SELECT d.qcd_outlet_code    AS "Outlet_Code:string", 
       d.qcd_quarter 
       ||' ' 
       ||d.qcd_year         AS "MCT_quarter:string", 
       Nvl(d.qcd_credit, 0) AS "MCT_Total_Credits_Earned", 
       d.rn                 AS "Display_Order:string" 
FROM   ordered d 
WHERE  rn <= 2; 

QCD_OUTLET_CODE行两行的结果:

+--------------------+--------------------+--------------------------+----------------------+
| Outlet_Code:string | MCT_quarter:string | MCT_Total_Crecits_Earned | Display_Order:string |
+--------------------+--------------------+--------------------------+----------------------+
|           10500106 | Q4 2014            | 387                      |                    1 |
|           10500106 | Q1 2015            | 482.75                   |                    2 |
|          144034911 | Q4 2014            | 269.5                    |                    1 |
|          144034911 | Q1 2015            | 276.5                    |                    2 |
+--------------------+--------------------+--------------------------+----------------------+

请忽略QCD_QUARTER的数量,它们是任意的。

因此Display_Order:string将显示1和2。 但是,如果每个QCD_OUTLET_CODE都有额外的行,我还需要显示每个组的底部2行(即2015/Q12015/Q2),我需要它们的值为1和2 Display_Order:string

运行上面相同的脚本将返回上面相同的结果(2014/Q42015/Q1)。 如果我在DESC子句中使用Partition,它将返回我想要的行,但Display_Order:string将没有正确的值(`2015 / Q2&#39;将给予1代替2)。

我希望从上面发布的第一个数据集中得到如下结果:

+--------------------+--------------------+--------------------------+----------------------+
| Outlet_Code:string | MCT_quarter:string | MCT_Total_Crecits_Earned | Display_Order:string |
+--------------------+--------------------+--------------------------+----------------------+
|           10500106 | Q1 2015            | 387                      |                    1 |
|           10500106 | Q2 2015            | 482.75                   |                    2 |
|          144034911 | Q1 2015            | 269.5                    |                    1 |
|          144034911 | Q2 2015            | 276.5                    |                    2 |
+--------------------+--------------------+--------------------------+----------------------+

值得一提的是,我试图实现的逻辑就像一个窗口,它滑过每个组以显示最近的两个季度,并相应地给出行号。

1 个答案:

答案 0 :(得分:1)

试试这个:

WITH ordered 
     AS (SELECT qcd_outlet_code, 
                qcd_year, 
                qcd_quarter, 
                qcd_credit, 
                Row_number() 
                  over ( 
                    PARTITION BY qcd_outlet_code 
                    ORDER BY qcd_outlet_code, qcd_year DESC, qcd_quarter DESC) 
                AS rn 
         FROM   QTR_CREDIT_DATA) 
SELECT d.qcd_outlet_code    AS "Outlet_Code:string", 
       d.qcd_quarter 
       ||' ' 
       ||d.qcd_year         AS "MCT_quarter:string", 
       Nvl(d.qcd_credit, 0) AS "MCT_Total_Credits_Earned", 
       Row_number() 
                  over ( 
                    PARTITION BY qcd_outlet_code 
                    ORDER BY qcd_outlet_code, qcd_year, qcd_quarter)
                           AS "Display_Order:string" 
FROM   ordered d 
WHERE  rn <= 2;