我有3个表的基本数据库。 “学生”“考试”和“分数”
对于每个测试,我需要列出所有测试成绩低于该测试平均值的学生。 (如果这有任何意义的话)
我有一个SQL查询,它只打印每个测试的平均分数。
SELECT t.Test_name, AVG(sc.Result) AS Avgscore
FROM Tests t
JOIN Scores sc ON t.id_Tests = sc.Tests_id_Tests
JOIN Students s ON sc.Students_id_Students = s.id_Students
WHERE t.id_Tests = $c"
($ c是来自for循环的参数,递增为将每个测试作为单独的表打印出来)
感谢任何帮助,谢谢
答案 0 :(得分:2)
更改您要显示的列的选择列表,但这会限制您想要的结果,对于给定的testid(将testXYZ替换为您正在搜索的实际测试)
SELECT t.Test_name, s.*, sc.*
FROM Tests t
JOIN Scores sc
ON t.id_Tests = sc.Tests_id_Tests
JOIN Students s
ON sc.Students_id_Students = s.id_Students
WHERE t.id_Tests = 'textXYZ'
and sc.result <
(select avg(x.result)
from scores x
where sc.Tests_id_Tests = x.Tests_id_Tests)
注意:要为所有测试运行此测试,并将分数限制在低于每个测试的平均值的分数,您只需将那一行留在where子句中并运行:
SELECT t.Test_name, s.*, sc.*
FROM Tests t
JOIN Scores sc
ON t.id_Tests = sc.Tests_id_Tests
JOIN Students s
ON sc.Students_id_Students = s.id_Students
WHERE sc.result <
(select avg(x.result)
from scores x
where sc.Tests_id_Tests = x.Tests_id_Tests)
答案 1 :(得分:0)
例如在PostgreSQL中你可以使用类似AVG(Score) OVER (GROUP BY id_Tests)
的窗口函数,但在MySQL中我建议使用子查询如下:
SELECT Scores.*, Students.*, t.Test_name, Avgscore
FROM Scores
JOIN Students ON sc.Students_id_Students = s.id_Students
JOIN
SELECT id_Tests, t.Test_name, AVG(sc.Result) AS Avgscore
FROM Tests t
JOIN Scores sc ON t.id_Tests = sc.Tests_id_Tests
-- WHERE id_Tests = $c
GROUP BY id_Tests, t.Test_name
) avgsc ON Scores.Tests_id_Tests=avgsc.id_Tests
WHERE Scores.Result < Avgscore
请注意,如果学生多次低于平均分数,可以多次列出 - 可能是也可能不是您想要的。
我注释掉过滤测试的行,因为我想一次检索所有测试更容易,但是如果你坚持在应用程序级别上对一个测试进行过滤,那么你可以通过取消注释来过滤这里。