每个类别的MySQL SUM TOP 2记录

时间:2019-05-19 07:20:30

标签: mysql sql greatest-n-per-group

我有一张学生成绩表,试图将所有学生在特定类别中的前2分加起来。我搜索了类似的帖子,但未获得正确答案

我曾尝试对分数进行求和,但仅获得两个学生而不是所有学生的成绩,并且它没有给我正确的价值。

SELECT SUM(marks) as totalmarks,stdid 
   FROM (( select marks,stdid 
               from finalresult 
               where `subjectcategory` = 1 
                    AND `classId`='3' AND `year`='2018'  
                    AND `term`='2' AND `type`='23' 
               order by marks  desc 
               LIMIT 2 ))t1  
   GROUP BY stdid

2 个答案:

答案 0 :(得分:0)

辅助子查询可能用于迭代

    SELECT
        stdid, marks
    FROM
    (
        SELECT stdid, marks,
               @rn := IF(@iter = stdid, @rn + 1, 1) AS rn,
               @iter := stdid
         FROM finalresult
         JOIN (SELECT @iter := NULL, @rn := 0) AS q_iter
        WHERE `subjectcategory` = 1 
          AND `classId`='3' 
          AND `year`='2018'  
          AND `term`='2' 
          AND `type`='23'  
        ORDER BY stdid, marks DESC
    ) AS T1
    WHERE rn <= 2

此解决方案忽略联系,每个学生证仅需两个。

Demo

答案 1 :(得分:0)

在MySQL 8+中,您可以这样做:

SELECT stdid, SUM(marks) as totalmarks
FROM (SELECT fr.*,
             ROW_NUMBER() OVER (PARTITION BY stdid ORDER BY marks DESC) as seqnm
      FROM finalresult fr
      WHERE subjectcategory = 1 AND 
            classId = 3 AND 
            year = 2018 AND  
            term = 2 AND
            type = 23 
     ) fr
WHERE seqnum <= 2
GROUP BY stdid;

请注意,我删除了单引号。看起来像数字的东西可能是。而且,您不应该混合使用类型-如果值确实存储为字符串,则将引号放回去。

在早期版本中,最简单的方法可能是使用变量,但是您必须非常小心。 MySQL不保证SELECT中变量的求值顺序,因此您不能在一个表达式中分配变量,而在另一个表达式中使用它。

一个复杂的表达式解决了这个问题。另外,最好在子查询中排序(最新版本的MySQL 5+要求这样做):

SELECT stdid, SUM(marks) as totalmarks
FROM (SELECT fr.*,
             (@rn := IF(@s = stdid, @rn + 1,
                        IF(@s := stdid, 1, 1)
                       )
             ) as seqnum
      FROM (SELECT fr.*
            FROM finalresult fr
            WHERE subjectcategory = 1 AND 
                  classId = 3 AND 
                  year = 2018 AND  
                  term = 2 AND
                  type = 23 
            ORDER BY stdid, marks DESC
           ) fr CROSS JOIN
           (SELECT @s = '', @rn := 0) params
WHERE seqnum <= 2
GROUP BY stdid;