2014-02-22 53 views
2

我有一个相当简单的3个表格数据库。 “学生”“测试”和“分数”SQL - 如何列出低于平均值的项目

对于每个测试,我需要列出所有测试分数低于该测试平均值的学生。 (如果这是有道理的)

我有一个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循环,其被递增到打印出每个测试作为一个单独的表)

任何帮助,将理解的是,得益于

回答

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) 

注意:要运行ALL测试,并将分数限制为低于每个测试平均值的分数,您只需将该行从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) 
+0

这个工作很完美。非常感谢你 :) –

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 

注意,一个学生可以列出含多处如果他们多次得到低于平均水平的分数,可能会或可能不是你想要的。

我注释了过滤测试的线路,因为我猜测一次检索所有测试更容易,但是如果您坚持在应用程序级别上对一个测试进行过滤,那么您可以通过取消注释来对其进行过滤。