mysql - 从多列中获取两个最大值

Posted

技术标签:

【中文标题】mysql - 从多列中获取两个最大值【英文标题】:mysql - Get two greatest values from multiple columns 【发布时间】:2013-05-16 03:26:08 【问题描述】:

我们可以使用GREATEST 从多个列中获取最大价值,如下所示

SELECT GREATEST(mark1,mark2,mark3,mark4,mark5) AS best_mark FROM marks

但现在我想从所有(5)分中获得两个最好的分数。

我可以在 mysql 查询上这样做吗?

表结构(我知道这是错误的 - 由某人创建):

student_id  | Name | mark1 | mark2 | mark3 | mark4 | mark5

【问题讨论】:

你的表结构是什么 @Jake1164 查询几乎解释了一切。 ***.com/questions/5360894/… @AndyThompson 这是不同的问题。 @jWeavers - 抱歉,我以为他想要 mark1-5 中的每一个的 top2,而不是五个中最好的。 【参考方案1】:

这不是最优雅的解决方案,但如果您无法更改表结构,那么您可以unpivot 数据,然后应用用户定义的变量来获取每个 student_id 的行号。代码将类似于以下内容:

select student_id, name, col, data
from
(
  SELECT student_id, name, col,
    data,
    @rn:=case when student_id = @prev then @rn else 0 end +1 rn,
    @prev:=student_id
  FROM 
  (
    SELECT student_id, name, col,
      @rn, 
      @prev,
      CASE s.col
        WHEN 'mark1' THEN mark1
        WHEN 'mark2' THEN mark2
        WHEN 'mark3' THEN mark3
        WHEN 'mark4' THEN mark4
        WHEN 'mark5' THEN mark5
      END AS DATA
    FROM marks
    CROSS JOIN 
    (
      SELECT 'mark1' AS col UNION ALL 
      SELECT 'mark2' UNION ALL 
      SELECT 'mark3' UNION ALL 
      SELECT 'mark4' UNION ALL 
      SELECT 'mark5'
    ) s
    cross join (select @rn := 0, @prev:=0) c
  ) s
  order by student_id, data desc
) d
where rn <= 2
order by student_id, data desc;

见SQL Fiddle with Demo。这将返回每个 student_id 的前 2 个标记。内部子查询执行与使用 UNION ALL 来取消透视类似的功能,但您不会多次查询表以获得结果。

【讨论】:

我认为 OP 想从所有 5 个标记列中创建一个列,然后挑选出最高的 2 个。不过不确定。无论如何,我的解决方案反映了这一点。【参考方案2】:

好的,这是一个适用于当前表结构的新答案:

SELECT `student_id`, `Name`, `mark` FROM (SELECT `student_id`, `Name`, `mark1` AS `mark` FROM `marks`
                                          UNION ALL
                                          SELECT `student_id`, `Name`, `mark2` AS `mark` FROM `marks`
                                          UNION ALL
                                          SELECT `student_id`, `Name`, `mark3` AS `mark` FROM `marks`
                                          UNION ALL
                                          SELECT `student_id`, `Name`, `mark4` AS `mark` FROM `marks`
                                          UNION ALL
                                          SELECT `student_id`, `Name`, `mark5` AS `mark` FROM `marks`) AS `marks`
ORDER BY `mark` DESC
LIMIT 2

【讨论】:

您还应该包括student_idname 否则......它不会显示正确的输出。【参考方案3】:

你可以创建一个临时表,然后

Create a temporary table in a SELECT statement without a separate CREATE TABLE

按如下方式查询该表

SELECT TOP 2 * FROM temp ORDER BY mark DESC

然后

删除临时表

【讨论】:

【参考方案4】:

我认为你应该改变你的数据库结构,因为水平有这么多标记(即作为字段/列)已经意味着你做错了。

而是将所有标记放在一个单独的表中,在其中创建多对多关系,然后执行必要的SELECTLIMIT

建议:

    创建一个名为mark_types 的表。列:idmark_type。一世 看到你目前有 5 种标记;这会很简单 添加其他类型。 更改您的 marks 表以容纳 3 列:idmark/grade/value,mark_type(本栏外约束到 mark_types)。 在连接和 GROUP BY mark_type 的帮助下编写您的 SELECT 查询。

【讨论】:

由某人创建的表结构,所以我不想干涉,只是我需要当前表结构的解决方案。

以上是关于mysql - 从多列中获取两个最大值的主要内容,如果未能解决你的问题,请参考以下文章

获取熊猫 groupby 对象中多列的最大聚合

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

怎么查询SQL数据库中一行多列的数据中最大值?

获取比较多列的最大值并返回特定值

Postgresql获取具有多列的每个组的最大值[重复]

从具有多列的 .txt 文件中查找最大值、最小值