如何使用他在某个科目上获得的最后成绩来查找学生的平均成绩,以防他获得更多成绩

问题描述 投票:0回答:4

我有两张桌子,一张用于

Grades
,一张用于
Students
Grades
表有一列
Student
是引用
Student.Id
的外键。

学生在不同科目上有多个成绩,有些学生在一个科目上有多个成绩。如果一个学生在一个科目上有一个以上的成绩,我如何只使用他在每个科目中获得的最后一个成绩而不是所有成绩来计算这些成绩的总平均分?

例如,如果一个学生有

Maths=3,History=5,Physics=4,History=7
我想只使用数学(3),物理(4)和最后一个历史(7)来做平均,没有历史(5)。

Check out this image

正如您在该图像中看到的那样,我有一个包含姓名、组、位置的学生表和一个包含这些成绩的成绩表。我想计算这些成绩的平均值,但如果同一科目的毕业生超过 1 人,则应使用该科目的最后成绩。在这种情况下,平均值应该是法语 (9) + 数学 (10) + 物理的最后成绩 5 的平均值。

对不起,我只是不知道在这种情况下该怎么做。我不熟悉使用关系数据库、外键等

sql sql-server
4个回答
0
投票

您可以使用以下SQL查询来计算每个学生每个科目最新成绩的总平均分:

SELECT s.Id, s.Name, g.Subject, AVG(g.Grade) AS Average
FROM Students s
JOIN Grades g ON s.Id = g.Student
JOIN (
  SELECT Student, Subject, MAX(Date) AS LatestDate
  FROM Grades
  GROUP BY Student, Subject
) latest_grades ON g.Student = latest_grades.Student
  AND g.Subject = latest_grades.Subject
  AND g.Date = latest_grades.LatestDate
GROUP BY s.Id, s.Name, g.Subject;

此查询根据外键关系连接 Students 和 Grades 表。然后它加入一个子查询,该子查询根据最大日期为每个学生-主题对选择最新成绩。最后,它使用 AVG 聚合函数计算每个学生每个科目的最新成绩的平均值,并将结果按学生和科目分组。


0
投票

使用 MAX() 函数获取每个科目的最新成绩。然后,您可以使用 AVG() 函数计算这些成绩的平均值。

举个例子:

    SELECT Students.Name, AVG(Grades.Grade)
FROM Students
JOIN (
    SELECT Student, Subject, MAX(Date) AS LatestDate
    FROM Grades
    GROUP BY Student, Subject
) AS LatestGrades ON Students.Id = LatestGrades.Student
JOIN Grades ON LatestGrades.Student = Grades.Student
    AND LatestGrades.Subject = Grades.Subject
    AND LatestGrades.LatestDate = Grades.Date
GROUP BY Students.Name

0
投票

假设一个合理的模式定义(请与问题中的列名和类型分享实际的模式定义,并且不要使用图像来做它),你想要这样的东西:

SELECT s.ID, s.Name, s.[Group], s.Location, AVG(g.Grade)
FROM 
( 
    SELECT Student, Subject, Grade
        ,row_number() over (partition by student, subject order by [ID] desc) rn
    FROM Grades
) g
INNER JOIN Students s ON s.Id = g.Student
WHERE rn = 1
GROUP BY s.ID, s.Name, s.[Group], s.Location

这使用 windowing 函数 进行分区,然后根据日期对每个学生/主题的行进行编号,这样您就可以限制在每个分区中的第一行并从那里取平均值。它应该比需要加入由

MAX(date)
选择的投影的解决方案表现得更好。

注意我在答案开头说了“合理的架构”。有一个基于图像的问题(同样:它在视图中被压扁并且几乎不可读 - 不要那样发布数据!)一个主题的多个等级存储在同一列中并以逗号分隔数据。这就是我们所说的 unreasonable 模式。在单个列中存储以逗号分隔的数据被认为是 BROKEN 模式设计:需要修复的东西。

另一个需要理解的重要事情是问题中没有显示的

Date
列的使用。 SQL 数据库明确拒绝为您的记录保留任何类型的自然顺序承担任何责任没有插入顺序、表顺序或磁盘顺序这样的东西,有很多东西可以导致数据库重新排列磁盘上的记录或以不同的顺序返回行,即使连续运行相同的查询。

因此,您必须有一种方法根据行中的实际数据来定义“最后成绩”。即使是顺序分配的 ID 也足够了,但我们需要something。否则,你将无法编写此查询! 是什么让

History(7)
而不是
History(5)


0
投票

我认为您必须先创建一个包含 LatestGrades 的新表,然后再创建 JOIN。看起来你甚至不需要最终输出中的 subj 列,只需要每个学生所有科目的平均分数。

与 新表AS (SELECT id, subject,grade, MAX(date) as LatestDate 从成绩 按学生、学科分组) 选择 Students.id, students.name, AVG (newtable.grade) AS Avggrade FROM (Newtable FULLJOIN 等级 ON Newtable.id=Grades.id) 在 students.id=grades.id 上完全加入学生

© www.soinside.com 2019 - 2024. All rights reserved.