如何获得多列之间的2个最大值?

How to get the 2 greatest values between multiple columns?

我正在尝试弄清楚如何从 5 个字段中获取 2 个最大值。我知道 greatest 函数,但我也不知道如何提取第二高的值。

基本上,table 有 5 个 NUMBER 类型字段。在这个例子中,最后两列是我想要的结果。

| Score1 | Score2 | Score3 | Score4 | Score5 | | Highest1_value | Highest2_value 
+--------+--------+--------+--------+--------+ +----------------+---------------
|    10  |    20  |    30  |    40  |   50   | |       50       |       40
|    20  |    20  |    12  |    17  |    0   | |       20       |       20
|     7  |     7  |     7  |     7  |   11.1 | |       11.1     |        7
|    10  |    10  |    10  |    10  |   10   | |       10       |       10

逆透视数据并使用 row_number 获得每个 ID 的前 2 个最高分数。

select id
,max(case when rnum=1 then val end) as highest_1
,max(case when rnum=2 then val end) as highest_2
from (select id,score,val,row_number() over(partition by id order by val desc) as rnum
      from (select * from t --replace this with your tablename
            unpivot (val for score in (score1,score2,score3,score4,score5)) p
          ) tbl
      ) tbl
group by id

如果我理解正确,你需要这个:

select your_table.*, REGEXP_SUBSTR(h.str, '^[^\-]+') AS h1, REGEXP_SUBSTR(h.str, '[^\-]+$') AS h2  FROM your_table
inner join  (
    select id, listagg(sc, '-') WITHIN GROUP (ORDER BY sc DESC) str FROM(
        select id, sc, row_number() over(partition by id order by sc desc) rn from (
            select id, sc FROM your_table
            UNPIVOT (sc for col in (Score1, Score2, Score3, Score4, Score5))
        ) tt
    )ttt
    where rn <= 2
    GROUP BY id
) h
ON your_table.id =  h.id

此解决方案避免了反转,只是大量的剪切&粘贴&修改:

SELECT 
   dt.*,
   CASE maxscore -- GREATEST on all but the highest value,
                 -- simplified to a "Valued Case" based on mathguy's comment
      WHEN score1 THEN Greatest(score2, score3, score4, score5)
      WHEN score2 THEN Greatest(score1, score3, score4, score5)
      WHEN score3 THEN Greatest(score1, score2, score4, score5)
      WHEN score4 THEN Greatest(score1, score2, score3, score5)
      ELSE Greatest(score1, score2, score3, score4)
   END
FROM
 (
   SELECT t.*,
      Greatest(Score1,Score2,Score3,Score4,Score5) AS maxscore
   FROM tab t
 ) dt

基于@vkp 和@mathguy 的评论,没有 Derived Table/Inline 观点:

SELECT 
   t.*,
   Greatest(Score1,Score2,Score3,Score4,Score5) as Highest1_value,
   CASE Greatest(Score1,Score2,Score3,Score4,Score5)-- GREATEST on all but the highest value
      WHEN score1 THEN Greatest(       score2,score3,score4,score5)
      WHEN score2 THEN Greatest(score1,       score3,score4,score5)
      WHEN score3 THEN Greatest(score1,score2,       score4,score5)
      WHEN score4 THEN Greatest(score1,score2,score3,       score5)
      ELSE             Greatest(       score1,score2,score3,score4)
   END as Highest2_value
FROM tab t