2017-04-14 30 views
6

我想弄清楚如何從5個字段中獲得2個最高值。我知道greatest函數,但我不知道如何提取第二高的值。如何獲取多列之間的2個最大值?

基本上,該表有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 
+0

你有每行的標識符嗎? –

+0

在你的第二行中,highest2_value應該是17我想......對嗎? – Teja

+0

vkp,是的,我有唯一的ID。 Teja,No,Score1和Score2都有20個,所以他們是最高的數字 – Rocco

回答

4

不透視數據並使用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 
+0

沒有unpivot在其他數據庫中是不可能的嗎?可能在mysql? – Teja

+0

你可以直接用'最大'或'最小'來獲得'max'或'min',而不需要改變(在MySQL中)。因爲OP需要2個最大值,所以我想不到'row_number'的方法。 –

+0

這僅返回Score4和Score5字段的值? – Rocco

3

如果我正確理解,你需要這樣的:

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 
+0

這個問題的正則表達式在我看來是一種矯枉過正。 –

+0

@vkp - 當然有可能做instr和子字符串,只是正則表達式是緊固東西出現在我的頭上 –

0

該解決方案避免了unpivot,只是很多切&粘貼&修改:基於@ VKP的&

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 

@ mathguy的評論沒有Derived Table/Inline View:

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 
+1

爲什麼一個'maxscore'計算呢?你可以將它包含在'case'表達式本身中。 –

+0

@vkp:當然,我已經得到了太多'GREATEST' :-) – dnoeth

+2

這可以進一步簡化。寫下這樣的'case'表達式:'case most(score1,...,score5)當score1 then ... when score2 then ...'(將它變成一個「簡單」的case表達式而不是一個「 「表達式;你不需要重複外部的'最大(...)',因爲它將在」左邊「)。 – mathguy

相關問題