Нахождение второго наибольшего значения из набора столбцов - PullRequest
1 голос
/ 06 ноября 2019

У меня был оригинальный вопрос, касающийся того, как найти наибольшее значение, и он был услужливо решен. Это было сделано с помощью этого запроса:

select t.*,
       (case greatest(score1, score2, score3)
             when score1 then 'score1'
             when score2 then 'score2'
             when score3 then 'score3'
        end) as high_score_name,
       greatest(score1, score2, score3) as high_score
from t;

Это работает как шарм исоздает желаемый вывод, который выглядит следующим образом:

+------+----------+----------+----------+--------------+
|  ID  |  score1  |  score2  |  score3  |  high_score  |
+------+----------+----------+----------+--------------+
|  123 |       14 |      561 |      580 |  score3      |
|  456 |      626 |      771 |      843 |  score3      |
|  789 |      844 |      998 |      904 |  score2      |
|  111 |      922 |      677 |      301 |  score1      |
|  222 |      665 |      578 |      678 |  score3      |
|  333 |      416 |      631 |      320 | score2       |
+------+----------+----------+----------+--------------+

Но теперь я пытаюсь найти второе значение greates, чтобы сгенерированный вывод выглядел так:

+------+----------+----------+----------+--------------+--------------+
|  ID  |  score1  |  score2  |  score3  |  high_score  | second_score |
+------+----------+----------+----------+--------------+--------------+
|  123 |       14 |      561 |      580 |  score3      | score2       |
|  456 |      626 |      771 |      843 |  score3      | score2       |
|  789 |      844 |      998 |      904 |  score2      | score3       |
|  111 |      922 |      677 |      301 |  score1      | score2       |
|  222 |      665 |      578 |      678 |  score3      | score1       |
|  333 |      416 |      631 |      320 | score2       | score1       |
+------+----------+----------+----------+--------------+--------------+

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

Ответы [ 2 ]

0 голосов
/ 08 ноября 2019

Я считаю, что лучший вариант сделать это - разворачивать таблицу (иметь по одной строке на счет), а затем ранжировать их. Если вы хотите получить точный результат с оригинальными результатами, вы можете либо снова повернуть таблицу, либо объединить результаты с помощью id.

Это мое предложение:

with input(id, score1, score2, score3) as (
    select 123, 14, 561,  580 union all
    select 456, 626, 771, 843 union all
    select 789, 844, 998, 904 union all
    select 111, 922, 677, 301 union all
    select 222, 665, 578, 678 union all
    select 333, 416, 631, 320
),
     unpivotted(id, score_label, score) as (
         select
             id,
             case x
                 when 1 then 'score1'
                 when 2 then 'score2'
                 when 3 then 'score3'
                 end,
             case x
                 when 1 then score1
                 when 2 then score2
                 when 3 then score3
                 end
         from input
                  cross join (select 1 as x union all select 2 union all select 3) as three
     ),
     ranked as (
         select *,
                rank() over (partition by id order by score desc) as rnk
         from unpivotted
     )
select distinct
    id,
    nth_value(score_label, 1) over (partition by id order by rnk rows between unbounded preceding and unbounded following ) as high_score_label,
    nth_value(score_label, 2) over (partition by id order by rnk rows between unbounded preceding and unbounded following) as second_score_label,
    nth_value(score, 1) over (partition by id order by rnk rows between unbounded preceding and unbounded following ) as high_score,
    nth_value(score, 2) over (partition by id order by rnk rows between unbounded preceding and unbounded following) as second_score
from ranked
order by id

Результат:

#   id  high_score_label    second_score_label  high_score  second_score
1   111 score1              score2              922         677
2   123 score3              score2              580         561
3   222 score3              score1              678         665
4   333 score2              score1              631         416
5   456 score3              score2              843         771
6   789 score2              score3              998         904
0 голосов
/ 06 ноября 2019

Если у вас нет связей, вы можете использовать другое case выражение:

select (case when score1 not in (least(score1, score2, score3), greatest(score1, score2, score3))
             then 'score1'
             when score1 not in (least(score1, score2, score3), greatest(score1, score2, score3))
             then 'score2'
             when score1 not in (least(score1, score2, score3), greatest(score1, score2, score3))
             then 'score3'
        end) as second_score

Это не обобщает хорошо для большего числа столбцов.

Если этоэто то, что вам нужно, я бы порекомендовал изменить модель данных, чтобы у вас были данные в строках , а не столбцах :

id    score    score_number
123      14         1
123     561         2
123     580         3
. . .  

Тогда ваши вопросы будут намного прощеответить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...