First three Groups with Highest Marks should have specific points

前端 未结 3 1339
谎友^
谎友^ 2020-12-21 15:59

my table

+------+-------+---------+-------+--------+
| Name | Group1| Section | Marks | Points |
+------+-------+---------+-------+--------+
| S1   | G1             


        
3条回答
  •  挽巷
    挽巷 (楼主)
    2020-12-21 16:09

    That was challenging.

    To solve it I used several methods:

    1. A CASE statement to convert the group's place in the top 3 into points.
    2. Rows numbering with a variable.
    3. INNER AND LEFT JOIN to merge the results together.

    The following query was tested on your fiddle and works:

    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`)
    

提交回复
热议问题