MySql-在复杂的查询中获取rowid /订单

时间:2018-11-17 10:50:22

标签: mysql sql

在与学生/年级等一起开展项目时,我需要不时更新前三名的学生。我想出了以下查询。但是,我很难获得他们的排名/顺序。我知道如何在一个简单的查询中执行此操作,但是在一个更复杂的查询中,它不起作用。 我正确地获取了所有其他列,并且使用尝试获取顺序的所有方法,有时我得到0(如代码的当前状态),有时得到的值是错误的(1、11、10、10 )等。

注意:我已经检查了各种问题(包括下面的问题),但是我不知道如何将它们放入查询中。

What is the best way to generate ranks in MYSQL?

摘要:

目标:
 -从marks获取每个学生的分数总和,将其除以表中的条目数(再次为marks)。学生来自给定的年级。
 -使用sum(mark)对这些学生进行排名。
 -获得前三名。
 -将该年级的前三名学生及其平均成绩(如TopStudents和ID放在sum表中。

表格:

学生表包含有关学生的信息,包括ID:

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int   (20) unsigned | NO   | PRI | NULL    | auto_increment |
| name        |varchar(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

分数表列出每项考试中每个学生的分数

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          |int    (20) unsigned | NO   | PRI | NULL    | auto_increment |
| idStudent   |int    (20) unsigned | NO   | FOR | NULL    |                |
| mark        |tinyInt (3) unsigned | NO   |     | NULL    |                |
| idExam      |int    (20) unsigned | NO   | FOR | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

成绩表具有成绩ID和名称:

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int   (20) unsigned | NO   | PRI | NULL    | auto_increment |
| name        |varchar(20) unsigned | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

班级表各个年级的班级。参考表

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int   (20) unsigned | NO   | PRI | NULL    | auto_increment |
| name        |varchar(20) unsigned | NO   |     | NULL    |                |
| idGrade     |  int  (20) unsigned | NO   | FOR | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

最后是臭名昭著的 TopStudents Table

+-------------+---------------------+------+-----+---------+----------------+
| Field       | Type                | Null | Key | Default | Extra          |
+-------------+---------------------+------+-----+---------+----------------+
| id          | int   (20) unsigned | NO   | PRI | NULL    | auto_increment |
| idStudent   | int   (20) unsigned | NO   | FOR | NULL    |                |
|  sumMarks   | int   (20) unsigned | NO   |     | NULL    |                |
|  rank       |tinyInt (1) unsigned | NO   |     | NULL    |                |
|  date       |date     unsigned    | NO   |     | NULL    |                |
+-------------+---------------------+------+-----+---------+----------------+

尝试: 尝试1 :错误:所有等级均为0

INSERT INTO topStudents(`date`, idStudent, `sum`, `order`)
SELECT
    '2018-10-10' AS DATE,
    student.id AS idStudent,
    AVG(marks.mark)
    @n = @n + 1 AS `order`
FROM
    marks
INNER JOIN student ON student.id = marks.idStudent
INNER JOIN class ON class.id = marks.idClass
INNER JOIN grade ON class.idGrade = grade.id
WHERE
    grade.id = 2
GROUP BY
    marks.idStudent
ORDER BY
    SUM(mark)
DESC
LIMIT 3

尝试2 :返回的排名:1、11、10

SET @n := 0;


INSERT INTO topStudents(`date`, idStudent, `sum`, `rank`)
SELECT
    '2018-10-10' AS DATE,
    tbl.idStudent AS idStudent,
    AVG(tbl.mark) AS `sum`,

    rnk AS `rank`
FROM (SELECT student.id AS idStudent, SUM(mark) AS mark FROM
    marks
INNER JOIN student ON student.id = marks.idStudent
INNER JOIN class ON class.id = marks.idClass
INNER JOIN grade ON class.idGrade = grade.id
WHERE
    grade.id = 2
GROUP BY
    marks.idStudent
ORDER BY
    SUM(mark)
DESC
LIMIT 3) AS tbl, (SELECT @n = @n + 1) AS rnk

1 个答案:

答案 0 :(得分:0)

在较新的MySQL版本中,在分配等级之前,您需要使用派生表进行排序:

INSERT INTO topStudents (`date`, idStudent, `sum`, `order`)
    SELECT date, idStudent, `sum`, (@n := @n + 1) AS `order`
    FROM (SELECT '2018-10-10' AS DATE, s.id AS idStudent,
                 SUM(m.mark) / (SELECT COUNT(*) FROM marks m2 WHERE m2.idStudent = m.idStudent) AS `sum`    
          FROM marks m JOIN
               student s
               ON s.id = m.idStudent JOIN
               class c
               ON c.id = m.idClass JOIN
               grade g
               ON c.idGrade = g.id
          WHERE g.id = 2
          GROUP BY m.idStudent
          ORDER BY SUM(mark) DESC
          LIMIT 3
         ) sm CROSS JOIN
         (SELECT @n := 0) params;

我几乎可以肯定sum的计算是不正确的,并且您确实打算使用avg(mark)。但是,这就是您所提出的逻辑。