First three Groups with Highest Marks should have specific points

前端 未结 3 1324
谎友^
谎友^ 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`)
    
    0 讨论(0)
  • 2020-12-21 16:29

    You can do an update join to achieve what you want;

    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;
    

    (posted this answer also to your second question where you seemed to ask for an update statement without noticing that it was a duplicate, moved it here)

    An SQLfiddle to test with.

    0 讨论(0)
  • 2020-12-21 16:36

    I have found a solution to list the groups with their allocated points but I was having a hard time storing the result back into myTable, i.e. doing an UPDATE on the table. I managed at last (see bottom of post!!).

    But first, here is the group score-table generator (group overview):

    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

    It gives me this list:

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

    I am back (26.08.2013, after having asked for help myself, see here) and can now provide the full answer:

    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
    

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

    And finally - off-topic:

    Dear user @user2594154, why have you bombarded this board with the same question 8 times?!?

    • Add specific points on highest marks Find sum of points and grouping
    • First three Groups with Highest Marks should have specific points (this post)
    • Grouping results by name and points Group each Sections by Points and
    • CompetitionName descending order Find highest points of two students
    • in a section Display 3 Maximum values of a Column, include duplicate
    • values with condition First three Groups with Highest Marks should
    • have specific points 5,3, 1 [duplicate]

    It would be much more helpful for everybody if you had kept your question in one post, explaining exactly what you want and also what you have tried yourself (!!). Then, in the course of the answering process, it is possible to edit it, making it more precise. New questions should only be posted, if their subject is actually different, see here.

    No hard feelings - I learnt a lot in the process of solving this problem of yours. ;-)

    0 讨论(0)
提交回复
热议问题