前三个具有最高分的组应具有特定点

时间:2013-08-23 13:59:34

标签: mysql sql

我的桌子

+------+-------+---------+-------+--------+
| Name | Group1| Section | Marks | Points |
+------+-------+---------+-------+--------+
| S1   | G1    | class1  |    55 |        |
| S16  | G1    | class1  |    55 |        |
| S17  | G1    | class1  |    55 |        |
| S28  |       | class1  |    55 |        |
| S2   |       | class2  |    33 |        |
| S3   |       | class1  |    25 |        |
| S4   | G88   | class2  |    65 |        |
| S5   | G88   | class2  |    65 |        |
| S30  | G66   | class2  |    66 |        |
| S31  | G66   | class2  |    66 |        |
| S32  |       | class1  |    65 |        |
| S7   | G5    | class1  |    32 |        |
| S18  | G5    | class1  |    32 |        |
| S19  | G5    | class1  |    32 |        |
| S33  | G4    | class2  |    60 |        |
| S34  | G4    | class2  |    60 |        |
| S35  | G4    | class2  |    60 |        |
| S10  |       | class2  |    78 |        |
| S8   | G8    | class1  |    22 |        |
| S20  | G8    | class1  |    22 |        |
| S21  | G8    | class1  |    22 |        |
| S9   |       | class2  |    11 |        |
| S12  |       | class3  |    43 |        |
| S22  | G9    | class1  |    20 |        |
| S23  | G9    | class1  |    20 |        |
| S24  | G9    | class1  |    20 |        |
| S13  | G55   | class2  |    33 |        |
| S36  | G55   | class2  |    33 |        |
| S14  |       | class2  |    78 |        |
| S25  | G10   | class1  |    55 |        |
| S26  | G10   | class1  |    55 |        |
| S27  | G10   | class1  |    55 |        |
+------+-------+---------+-------+--------+

SQL FIDDLE:http://www.sqlfiddle.com/#!2/5ce6c/1

我试图给每个部分中分数最高的前3组提供具体要点。 我想为第一高组中的每个学生增加5分,第二高分为3分,第三高组为1分。 。组可能会出现重复标记。

我正在使用以下代码,此代码适用于个别学生,不知道如何给小组分数。

select t1.Name, t1.Section, t1.Marks from myTable t1 join 
(select Section, substring_index(group_concat (distinct Marks order by Marks desc),    
',', 3) as Marks3  from myTable where Section = 'class1' group by Section ) tsum  
on t1.Section = tsum.Section and find_in_set(t1.Marks, tsum.Marks3) > 0 
ORDER BY Section, Marks DESC, ID Desc

我的最终输出会查找一个部分。

 +---------------------------------------------+
 | | Name | Group1| Section | Marks | Points | |
 +---------------------------------------------+
 | | S1   | G1    | class1  |    55 |    5   | |
 | | S16  | G1    | class1  |    55 |    5   | |
 | | S17  | G1    | class1  |    55 |    5   | |
 | | S28  |       | class1  |    55 |        | |
 | | S2   |       | class2  |    33 |        | |
 | | S3   |       | class1  |    25 |        | |
 | | S4   | G88   | class2  |    65 |        | |
 | | S5   | G88   | class2  |    65 |        | |
 | | S30  | G66   | class2  |    66 |        | |
 | | S31  | G66   | class2  |    66 |        | |
 | | S32  |       | class1  |    65 |        | |
 | | S7   | G5    | class1  |    32 |    3   | |
 | | S18  | G5    | class1  |    32 |    3   | |
 | | S19  | G5    | class1  |    32 |    3   | |
 | | S33  | G4    | class2  |    60 |        | |
 | | S34  | G4    | class2  |    60 |        | |
 | | S35  | G4    | class2  |    60 |        | |
 | | S10  |       | class2  |    78 |        | |
 | | S8   | G8    | class1  |    22 |   1    | |
 | | S20  | G8    | class1  |    22 |   1    | |
 | | S21  | G8    | class1  |    22 |   1    | |
 | | S9   |       | class2  |    11 |        | |
 | | S12  |       | class3  |    43 |        | |
 | | S22  | G9    | class1  |    20 |        | |
 | | S23  | G9    | class1  |    20 |        | |
 | | S24  | G9    | class1  |    20 |        | |
 | | S13  | G55   | class2  |    33 |        | |
 | | S36  | G55   | class2  |    33 |        | |
 | | S14  |       | class2  |    78 |        | |
 | | S25  | G10   | class1  |    55 |   5    | |
 | | S26  | G10   | class1  |    55 |   5    | |
 | | S27  | G10   | class1  |    55 |   5    | |
 +---------------------------------------------+

请帮帮我。

3 个答案:

答案 0 :(得分:3)

这很有挑战性。

为了解决这个问题,我使用了几种方法:

  1. 一个CASE statement,用于将前3名中的群组转换为分数。
  2. Rows numbering带有变量
  3. INNER LEFT JOIN将结果合并在一起。
  4. 以下查询已经在您的小提琴上进行了测试并且有效:

    SELECT t1.`id`,  t1.`name`,  t1.`group1`,
           t1.`section`, t1.`MARKS`, `t_group_points`.`points`
    
    FROM   `students` t1
    
    #--- Join  groups' points to the students
    LEFT JOIN (
        (
            #---- Join all groups and give points to top 3 avg's groups ----
            SELECT `t4`.`group1`, `t_points`.`points`
            FROM   (SELECT   `t3`.`group1`, AVG(`t3`.`marks`) AS `avg`
                    FROM     `students` `t3`
                    WHERE    (`t3`.`section` = 'class1') AND
                             (`t3`.`group1` IS NOT NULL)
                    GROUP BY `t3`.`group1`) `t4`
    
            INNER JOIN (
                  #---------- Select top 3 avarages ----------
                  (SELECT `top`.`avg`,
                          #-- Convert row number to points ---
                          CASE @curRow := @curRow + 1  
                               WHEN '1' THEN 5
                               WHEN '2' THEN 3
                               WHEN '3' THEN 1
                               ELSE NULL END 'points'
    
                  FROM (SELECT DISTINCT `t_avg`.`avg`
                        FROM   (SELECT   `t2`.`group1`, AVG(`t2`.`marks`) AS `avg`
                                FROM     `students` `t2`
                                WHERE    (`t2`.`section` = 'class1') AND
                                         (`t2`.`group1` IS NOT NULL)
                                GROUP BY `group1`) `t_avg`
                        ORDER BY `avg` DESC
                        LIMIT 0, 3) `top`, (SELECT @curRow:=0) r
                  ) AS `t_points`)
             ON (`t_points`.`avg` = `t4`.`avg`)      
        ) AS `t_group_points`)
    ON (`t_group_points`.`group1` = `t1`.`group1`)
    

答案 1 :(得分:1)

我找到了一个解决方案来列出已分配点的组,但我很难将结果存回myTable,即在表上执行UPDATE。我最后管理了(见帖子的底部!! )。

但首先,这是小组得分表生成器(小组概述):

SELECT mg,ms,mm,
  CASE WHEN @s=ms THEN 
    CASE WHEN @m=mm THEN @i 
         WHEN @i>2 THEN @i:=@i-2 
         ELSE null END
  ELSE @i:=5 END pt,
  @g:=mg gr,@s:=ms,@m:=mm 
FROM (
  SELECT group1 mg,section ms,max(marks) mm FROM mytable
  WHERE group1>''
  GROUP BY group1,section
) m 
ORDER BY ms,mm desc,mg

http://sqlfiddle.com/#!2/bea2a2/1

它给了我这个清单:

|  MG |     MS | MM |     PT |  GR | @S:=MS | @M:=MM |
------------------------------------------------------
|  G1 | class1 | 55 |      5 |  G1 | class1 |     55 |
| G10 | class1 | 55 |      5 | G10 | class1 |     55 |
|  G5 | class1 | 32 |      3 |  G5 | class1 |     32 |
|  G8 | class1 | 22 |      1 |  G8 | class1 |     22 |
|  G9 | class1 | 20 | (null) |  G9 | class1 |     20 |
| G66 | class2 | 66 |      5 | G66 | class2 |     66 |
| G88 | class2 | 65 |      3 | G88 | class2 |     65 |
|  G4 | class2 | 60 |      1 |  G4 | class2 |     60 |
| G55 | class2 | 33 | (null) | G55 | class2 |     33 |

上午(2013年8月26日,在我自己寻求帮助之后,请参阅here),现在可以提供完整答案

SET @s:=@m:=@i:='a'; -- variables *MUST* be "declared" in some
                     -- way, otherwise UPDATE will not work!

UPDATE mytable INNER JOIN 
(SELECT mg,ms,mm,
   CASE WHEN @s=ms THEN 
     CASE WHEN @m=mm THEN @i 
          WHEN @i>2 THEN @i:=@i-2 
          ELSE null END
   ELSE @i:=5 END pt,
   @s:=ms,@m:=mm 
 FROM (
   SELECT group1 mg,section ms,max(marks) mm FROM mytable
   WHERE group1>''
   GROUP BY group1,section
 ) m 
 ORDER BY ms,mm desc,mg
) t ON mg=group1 AND ms=section AND mm=marks
SET Points=pt

http://sqlfiddle.com/#!2/bb7f2

最后 - 离题:

亲爱的用户@ user2594154,你为什么要用相同的问题 8次轰炸这个主板??

  • 在最高分上添加特定点查找分数和分组总和
  • 前三个标记最高的群体应该有特定点(此帖
  • 按名称和点对结果进行分组按点和
  • 对每个部分进行分组
  • 竞争名称降序查找两名学生的最高分
  • 在显示3列的最大值的部分中,包括重复的
  • 带条件的值前三个具有最高分的组
  • 具有特定点5,3,1 [重复]

如果您将问题保留在一个帖子中,解释您想要的以及您自己尝试过的内容,那对每个人都会更有帮助(!!)然后,在回答过程中,可以对其进行编辑,使其更加精确。只应发布新问题,如果其主题实际上不同,请参阅here

没有难过的感觉 - 我在解决你的这个问题的过程中学到了很多东西。 ; - )

答案 2 :(得分:0)

您可以进行更新加入以达到您想要的效果;

UPDATE students
JOIN (
  SELECT marks, (@sp:=@sp-2) a
  FROM (
    SELECT distinct marks FROM students
    WHERE section='class1' AND group1 IS NOT NULL
    GROUP BY group1 ORDER BY marks DESC LIMIT 3
  ) b, (SELECT @sp:=7) c
) d
SET students.points = d.a 
WHERE students.marks = d.marks
  AND section='class1'
  AND group1 IS NOT NULL;

(也将这个答案发布到你的第二个问题,你似乎要求更新声明而没有注意到它是重复的,在此处移动了它)

An SQLfiddle to test with