Mysql从每个组中查找多个行

时间:2013-11-22 07:41:01

标签: mysql sql

我有一个包含3列的表格student_idsection_idmarks,每个列都包含整数值,student_id是具有唯一值的主要字段。现在我需要为下面的3个场景编写查询(PS:这仅用于学习目的,如果可能的话,如果可以向我展示一些替代的逻辑方法,那将会很棒):

  1. 找到每个部分排名第3的学生。
  2. 找到每个部分排名第2,第3和第4的学生。
  3. 找到在每个部分排名第4的学生,如果有任何约束,如果一个部分中有多个学生具有相同的分数,则跳过下一个等级。因此,假设有3名学生得到相同的分数,将他们排在第2部分的第2名,然后第3名和第4名被跳过,而下一名得分低于他们的学生将排名第5。
  4. 对于我试过的第一个:

    SELECT * FROM `students` s 
     WHERE s.student_id=
    (
      SELECT student_id 
        FROM students 
       WHERE s.section_id=section_id 
       ORDER BY marks DESC 
       LIMIT 2,1
    ) 
     GROUP BY section_id 
     ORDER BY marks DESC
    

    虽然我不确定优化,但这有效。

    对于下一个我尝试使用IN因为否则我无法在子查询中获取多行,但它说mysql不支持LIMIT IN有没有办法为第二种情况修改这个查询?

    最后,我不知道如何处理第三个问题。

    我在http://sqlfiddle.com/#!2/6442fb/1

    创建了一个测试表

    任何帮助表示感谢。

1 个答案:

答案 0 :(得分:0)

不幸的是,MySQL仍然缺乏对分析功能的支持。具体而言,RANK()RANK_DENSE()会非常有用。模仿它们的一种方法是使用用户变量:

SELECT student_id, section_id, marks
  FROM
(
  SELECT s.*, @n := IF(@s = section_id, IF(@m = marks, @n, @n + 1), 1) rank, 
         @s := section_id, @m := marks
    FROM students s CROSS JOIN (SELECT @n := 0, @s := NULL, @m := NULL) i
   ORDER BY section_id, marks DESC
) q
 WHERE rank = 3
 ORDER BY marks DESC;

SELECT student_id, section_id, marks
  FROM
(
  SELECT s.*, @n := IF(@s = section_id, IF(@m = marks, @n, @n + 1), 1) rank, 
         @s := section_id, @m := marks
    FROM students s CROSS JOIN (SELECT @n := 0, @s := NULL, @m := NULL) i
   ORDER BY section_id, marks DESC
) q
 WHERE rank BETWEEN 2 AND 4
 ORDER BY section_id, marks DESC;

SELECT student_id, section_id, marks
  FROM
(
  SELECT s.*, @n := IF(@s = section_id, @n + 1, 1),
         @rn := IF(@m = marks, @rn, @n) rank,
         @s := section_id, @m := marks
    FROM students s CROSS JOIN (SELECT @n := 0, @rn := 0, @s := NULL, @m := NULL) i
   ORDER BY section_id, marks DESC
) q
 WHERE rank = 4
 ORDER BY marks DESC;

这是 SQLFiddle 演示