在 Oracle 19C 中的多个列上排名

Rank on multiple columns in Oracle 19C

能否请您推荐一种在 Oracle 19c 中计算多列排名的简单方法。

For instance - considering [ Mango | 1 | 1 ] group from the table

NAME    DAY PROD    S       M       P   AMT1    AMT2    AMT3
----------------------------------------------------------
MANGO   1   1       -2.75   3       15  21.277  80      80
MANGO   1   1       -2.75   1.5     21  27.778  80      80
MANGO   1   1       -2.75   3       21  27.778  80      80
MANGO   1   1       -2.75   3       14  20      80      80

Expected output : 2nd row

对于每个组 [NAME, DAY, PROD],我需要确定一个具有 min[abs(S)] 值的行。 如果此 returns 多行具有相同的值 [NAME, DAY, PROD, S],则要考虑的下一列是具有 max(AMT1) 的行。 同样,如果使用相同的 [NAME, DAY, PROD, S, AMT1] 获取多于一行,下一个要考虑的因素是 min(M)。 最后,min(P).

总的来说,每个组 [NAME, DAY, PROD] 应该返回一行 考虑排列行的顺序为 min(abs(S)) -> max(AMT1) -> min(M) -> min(P)

示例记录的预期输出DB_Fiddle

中提供的 SQL
NAME    DAY PROD    S       M   P   AMT1    AMT2    AMT3                final deciding factor
----------------------------------------------------------
APPLE   1   1       -2.5    3   21  27.778  80      80          --->    min(abs(S))
APPLE   8   0.5     -1.25   3   10  51.02   90      90          --->    max(AMT1)
MANGO   5   1       -1.75   3   14  24      83.333  83.333      --->    min(P)
MANGO   1   1       -2.75   1.5 21  27.778  80      80          --->    min(M)

只需使用ROW_NUMBER()解析函数:

SELECT *
FROM   (
  SELECT t.*,
         ROW_NUMBER() OVER (
           PARTITION BY name, day, prod
           ORDER BY ABS(s) ASC,
                    amt1   DESC,
                    m      ASC,
                    p      ASC
         ) AS rn
  FROM   test3 t
)
WHERE rn = 1;

其中,对于示例数据,输出:

NAME DAY PROD S M P AMT1 AMT2 AMT3 RN
APPLE 1 1 -2.5 3 21 27.778 80 80 1
APPLE 8 .5 -1.25 3 10 51.02 90 90 1
MANGO 1 1 -2.75 1.5 21 27.778 80 801
MANGO 5 1 -1.75 3 14 24 83.333 83.333 1

db<>fiddle here