如何获得多列之间的 2 个最大值?
Posted
技术标签:
【中文标题】如何获得多列之间的 2 个最大值?【英文标题】:How to get the 2 greatest values between multiple columns? 【发布时间】:2017-04-14 19:03:52 【问题描述】:我试图弄清楚如何从 5 个字段中获取 2 个最高值。 greatest
函数我知道,但我也不知道如何提取第二高的值。
基本上,该表有 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
【问题讨论】:
每一行都有一个标识符吗? 我猜在第二行中,highest2_value 应该是 17.. 对吗? vkp,是的,我有唯一的 ID。 Teja,No,Score1 和 Score2 都有 20,所以它们是最高的数字 预期的输出应该是什么样子?请将其发布为格式化文本。 【参考方案1】:取消透视数据并使用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
【讨论】:
其他数据库中没有unpivot就不行吗?可能在mysql里? 您可以直接使用greatest
或least
获得max
或min
,而无需取消透视(在MySQL 中)。因为 OP 需要 2 个最大值,所以我想不出不使用 row_number
的方法。
这仅返回来自 Score4 和 Score5 字段的值?
排序必须在val
字段而不是row_number
中的score
。我改变了它,现在应该可以按预期工作了。
现在可以了,我接受这个答案,因为这是第一个。谢谢大家【参考方案2】:
如果我理解正确,你需要这个:
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
【讨论】:
在我看来,这个问题的正则表达式是矫枉过正。 @vkp - 当然也可以对 instr 和 substring 做同样的事情,只是正则表达式是我脑海中出现的最快的东西【参考方案3】:这个解决方案避免了反透视,只是大量的剪切&粘贴&修改:
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 的没有派生表/内联视图的cmets:
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
【讨论】:
为什么要进行maxscore
计算?您可以将其包含在 case
表达式本身中。
这可以进一步简化。像这样编写case
表达式:case greatest(score1,...,score5) when score1 then ... when score2 then...
(使其成为“简单”案例表达式,而不是“搜索”案例表达式;您不需要重复外部 greatest(...)
,因为它将在“左侧”)。以上是关于如何获得多列之间的 2 个最大值?的主要内容,如果未能解决你的问题,请参考以下文章