2014-02-22 51 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 

注意,一個學生可以列出含多處如果他們多次得到低於平均水平的分數,可能會或可能不是你想要的。

我註釋了過濾測試的線路,因爲我猜測一次檢索所有測試更容易,但是如果您堅持在應用程序級別上對一個測試進行過濾,那麼您可以通過取消註釋來對其進行過濾。