У меня есть таблица, которая выглядит так:

--------------------------------
ENTITY  |  VALUE X  |  VALUE Y  
--------------------------------
AAA     |    100    |    50     
--------------------------------
BBB     |     0     |    20      
--------------------------------
CCC     |    null   |    null   
--------------------------------
DDD     |    100    |    100    
--------------------------------

Я хочу определить, какой из столбцов (X или Y) имеет наибольшее значение (в моем фактическом наборе данных есть пять столбцов, но для простоты я использую два).

Если оба значения равны нулю, я бы хотел, чтобы результат был нулевым.

В случае ничьей я хотел бы иметь установленный ранг для тай-брейков (x> y> z ...)

Желаемый результат будет выглядеть так, как показано ниже

---------------------------------------------------
ENTITY  |  VALUE X  |  VALUE Y  |  DESIRED OUTPUT  
---------------------------------------------------
AAA     |    100    |    50     |         X        
---------------------------------------------------
BBB     |     0     |    20     |         Y          
---------------------------------------------------
CCC     |    null   |    null   |       null       
---------------------------------------------------
DDD     |    100    |    100    |         X        
---------------------------------------------------

Я все еще пытаюсь использовать MAX(), однако я думаю, что это в основном предназначено для сравнения строк в столбце, а не наоборот ...

Любая помощь будет очень признателен. Спасибо!

1
Sebastian Hubard 9 Сен 2020 в 00:12

2 ответа

Лучший ответ

Вы можете сделать это с помощью логики case. Предполагая, что ни одно из значений не равно NULL:

select t.*,
       (case greatest(x, y)
            when x then 'x'
            when y then 'y'
        end) 
from t;
1
Gordon Linoff 8 Сен 2020 в 21:20

Если у вас более двух столбцов, как описано в вопросе, то наиболее масштабируемый подход использует боковое соединение. Идея состоит в том, чтобы преобразовать столбцы в строки, отфильтровать значения null, затем упорядочить их по убыванию значения и оставить только верхнюю строку:

select t.*, x.*
from mytable t
outer apply (
    select col
    from (
        select 'X' col, t.value_x val from dual
        union all select 'Y', t.value_y from dual
    ) x
    where x.val is not null
    order by x.val desc
    fetch first 1 row only
) x

Демонстрация DB Fiddlde :

ENTITY | VALUE_X | VALUE_Y | COL 
:----- | ------: | ------: | :---
AAA    |     100 |      50 | X   
BBB    |       0 |      20 | Y   
CCC    |    null |    null | null
DDD    |     100 |     100 | X   
1
GMB 8 Сен 2020 в 21:17