MySql - 在复杂查询中获取 rowid / order [关闭]

Posted

技术标签:

【中文标题】MySql - 在复杂查询中获取 rowid / order [关闭]【英文标题】:MySql - Getting rowid / order in a complex query [closed] 【发布时间】:2018-11-17 10:50:21 【问题描述】:

与学生/成绩/等一起工作,我需要每隔一段时间更新前 3 名学生。我想出了下面的查询。但是,我无法获得他们的排名/顺序。我知道如何在一个简单的查询中做到这一点,但在一个更复杂的查询中,它不起作用。 我正确地获取了所有其他列,并且使用我尝试获取订单的所有方法,有时我得到 0(如代码的当前状态),有时值是错误的(1、11、10 ) 等。

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

What is the best way to generate ranks in mysql?

总结: 目标: - 从marks 获取每个学生的分数总和,除以表中的条目数(同样是marks)。学生来自给定年级。 - 使用sum(mark) 对这些学生进行排名。 - 获得前三名。 - 将该年级的前三名学生放在TopStudents 表中,并附上他们的平均分(如sum)和他们的身份证。

表格:

Students 表包含有关学生的信息,包括 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

【问题讨论】:

见Why should I provide an MCVE for what seems to me to be a very simple SQL query @Strawberry 我进行了相应的编辑 【参考方案1】:

在更新的 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)。但是,这是您在问题中的逻辑。

【讨论】:

为简单起见,我修剪了一些查询,这导致了sum 错误。实际上,我需要将它除以我的问题中未显示的其他参数,所以我认为这样做可以。 Anywho,您的查询返回的结果类似于我的一项测试(我尝试了很多我不记得了):order (ranks) where all 0. @skullz 。 . .有一个错字——作业需要使用:=,而不是= 工作就像一个魅力。非常感谢

以上是关于MySql - 在复杂查询中获取 rowid / order [关闭]的主要内容,如果未能解决你的问题,请参考以下文章

当我们有多个表时获取 Querydsl Oracle Rowid

使用DBMS_ROWID获取被阻塞行的rowid

postgres 9.2 中的 ROWID 等效项

Oracle查询去除重数据

MySQL使用Group Bu返回不正确的值[重复]

Oracle ROWID 值