Ранжирование по нескольким столбцам в Oracle 19C

#oracle #rank #oracle19c #ranking-functions #oracle-analytics

Вопрос:

Не могли бы вы, пожалуйста, предложить простой способ вычисления ранга по нескольким столбцам в 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
 

Для каждой группы [ИМЯ, ДЕНЬ, РЕЗУЛЬТАТ] мне нужно определить строку, имеющую минимальное значение[abs(S)].
Если это возвращает несколько строк с одинаковыми значениями [NAME, DAY, PROD, S], то следующим столбцом, который следует рассмотреть, является строка с максимальным значением(AMT1).
Опять же, если более чем одна строка извлекается с одним и тем же [ИМЕНЕМ, ДНЕМ, РЕЗУЛЬТАТОМ, S, AMT1], следующим фактором, который следует учитывать, является min(M).
И, наконец, мин(Р).

В целом, для каждой группы должна быть возвращена одна строка [ИМЯ, ДЕНЬ, РЕЗУЛЬТАТ] с учетом порядка ранжирования строк как min(abs(S)) -> max(AMT1) ->> min(M) ->>> min(P)>>>

Ожидаемые выходные данные для выборочных записей : Предоставленные списки SQL в DB_Fiddle

 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)
 

Ответ №1:

Просто используйте 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;
 

Который для выборочных данных выводит:

Имя день подгонять 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
манго 1 1 -2.75 1.5 21 27.778 80 801
манго 5 1 -1.75 3 14 24 83.333 83.333 1

бд<>скрипка <>здесь

Комментарии:

1. Спасибо! @MT0 🙂