Mysql SQL中同一行的列值中第二高的值

Mysql SQL中同一行的列值中第二高的值,mysql,sql,Mysql,Sql,样本数据: id score1 score2 score3 score4 1 10 05 30 50 2 05 15 10 00 3 25 10 05 15 预期结果集: id col_value 1 30 2 10 3 15 假设没有关系,可以使用大的大小写表达式: select t.*, (case when score1 > score2 and score1 >

样本数据:

id score1 score2 score3 score4
1  10     05      30    50
2  05     15      10    00
3  25     10      05    15
预期结果集:

id col_value
1    30
2    10
3    15

假设没有关系,可以使用大的
大小写
表达式:

select t.*,
       (case when score1 > score2 and score1 > score3 and score1 < score 4 then score1
             when score1 > score2 and score1 < score3 and score1 > score 4 then score1
             when score1 < score2 and score1 > score3 and score1 > score 4 then score1
             when score2 > score1 and score2 > score3 and score2 < score 4 then score2
             when score2 > score1 and score2 < score3 and score2 > score 4 then score2
             when score2 < score1 and score2 > score3 and score2 > score 4 then score2
             . . .
        end) as second_score          
from t;
选择t.*,
(如果分数1>2分,分数1>3分,分数1<4分,则得分1
当score1>score2且score1Score4时,则得1分
当得分1<得分2和得分1>得分3和得分1>得分4时,则得分1
当得分2>得分1和得分2>得分3和得分2<得分4时,则得分2
当score2>score1和score2得分4时,则得分2
当得分2<得分1和得分2>得分3和得分2>得分4时,则得分2
. . .
结束)作为第二个_分数
从t;

不过,一般来说,这类问题表明数据结构存在问题。我猜想您真的应该有一个表,每个
id
score
(可能还有一个
score
数字)有一行。这在SQL中通常更容易操作。

使用
大小写表达式告诉您在
最大()调用中忽略哪个分数

SELECT id,
    CASE GREATEST(score1, score2, score3, score4)
        WHEN score1 THEN GREATEST(score2, score3, score4)
        WHEN score2 THEN GREATEST(score1, score3, score4)
        WHEN score3 THEN GREATEST(score1, score2, score4)
        ELSE GREATEST(score1, score2, score3)
    END AS col_value
FROM your_table ;
此解决方案很容易推广到任意数量的列


和一个不带
大小写的变体,同时使用
最大值()
最小值()


考虑以下更容易概括的情况:

DROP TABLE IF EXISTS my_table;

CREATE TABLE my_table 
(id INT NOT NULL
,score_no INT NOT NULL
,score INT NOT NULL
,PRIMARY KEY(id,score_no)
);

INSERT INTO my_table VALUES
(1, 1 ,10),
(1 ,2 ,05),
(1 ,3 ,30),
(1 ,4 ,50),
(2 ,1 ,05),
(2 ,2 ,15),
(2 ,3 ,10),
(2 ,4 ,00),
(3 ,1 ,25),
(3 ,2 ,10),
(3 ,3 ,05),
(3 ,4 ,15);

SELECT id
     , score_no
     , score 
  FROM 
     ( SELECT x.*
            , CASE WHEN @prev=id THEN @i:=@i+1 ELSE @i:=1 END rank
            , @prev:=id 
         FROM my_table x
            , (SELECT @prev:=null,@i:=0) vars 
        ORDER 
           BY id
            , score DESC
            , score_no 
     ) a
 WHERE rank = 2;
 +----+----------+-------+
 | id | score_no | score |
 +----+----------+-------+
 |  1 |        3 |    30 |
 |  2 |        3 |    10 |
 |  3 |        4 |    15 |
 +----+----------+-------+

如果分数相等,此解决方案会选择“分数”较低的一个。

使用
UNPIVOT
尝试此查询

    CREATE TABLE #my_table
(id INT NOT NULL, score1 INT NOT NULL, score2 INT NOT NULL, score3 INT NOT NULL, score4 INT NOT NULL) 

INSERT INTO #my_table VALUES(1,  10,     05,      30,    50)
INSERT INTO #my_table VALUES(2,  05,     15,      10,    00)
INSERT INTO #my_table VALUES(3,  25,     10,      05,    15)

;WITH getHighestValue as (
SELECT id, Scores, ScoreText, ROW_NUMBER() OVER(PARTITION BY id ORDER BY Scores DESC) AS Ranks
FROM #my_table
UNPIVOT(
Scores for ScoreText in (score1,score2,score3,score4)
) unpiv
)
SELECT id, Scores as col_value 
FROM getHighestValue
WHERE Ranks = 2
结果:


如果出现平局,您会怎么做?最大值(score1、score2等)返回第一个最高值。我正在寻找第二个最高值来替代GordonLinoff的答案,你可以把它转为行并应用一个排名函数。@ SATYASAINATH应该澄清问题,而不是评论。@ SATYASAINATH。如果你有改变表结构的范围和时间,请考虑Strawberry的解决方案。您确实需要规范化您的表。您当前的表结构根本不可伸缩。我有22个这样的列。我只是在这里分享了一个示例列。谢谢你的快速回复。还有没有其他机会得到这个第二高的值。?我可以很容易地得到第一个最高值使用最大。为什么你有22列这样?这听起来像是一个规范化问题。@satyasainath。只能回答你实际提出的问题。这个问题显然是关于4栏的。如果这不是你真正想要的,你应该问另一个问题。如果你改变这个问题,你将使我的答案无效,这将吸引选票。我的答案更容易概括。非常感谢你的逻辑。这将有助于唯一可预见的问题将是,如果有重复的分数也是最高的。请参阅ID 4-预期
2
收到
3
OP从未回答Gordon关于如何处理重复项的问题。此外,这不是唯一可以预见的问题:-(@Barmar nice idea!。我使用您的主题添加了一个变体;)
    CREATE TABLE #my_table
(id INT NOT NULL, score1 INT NOT NULL, score2 INT NOT NULL, score3 INT NOT NULL, score4 INT NOT NULL) 

INSERT INTO #my_table VALUES(1,  10,     05,      30,    50)
INSERT INTO #my_table VALUES(2,  05,     15,      10,    00)
INSERT INTO #my_table VALUES(3,  25,     10,      05,    15)

;WITH getHighestValue as (
SELECT id, Scores, ScoreText, ROW_NUMBER() OVER(PARTITION BY id ORDER BY Scores DESC) AS Ranks
FROM #my_table
UNPIVOT(
Scores for ScoreText in (score1,score2,score3,score4)
) unpiv
)
SELECT id, Scores as col_value 
FROM getHighestValue
WHERE Ranks = 2