2010-03-26 31 views
1

我正在使用MySQL和PHP爲Flash遊戲構建數據層。檢索關卡列表非常簡單,但我試圖獲取關卡的平均評分以及指針信息時遇到了障礙。下面是一個例子的數據集:來自兩個表的MySQL評分

水平表:

level_id | level_name 
     1 | Some Level 
     2 | Second Level 
     3 | Third Level 

評級表:

rating_id | level_id | rating_value 
     1 | 1  |  3 
     2 | 1  |  4 
     3 | 1  |  1 
     4 | 2  |  3 
     5 | 2  |  4 
     6 | 2  |  1 
     7 | 3  |  3 
     8 | 3  |  4 
     9 | 3  |  1 

我知道這需要加入,但我無法弄清楚如何獲得平均評分值當我請求一個級別列表時,基於level_id。這就是我想要做的事:

SELECT levels.level_id, AVG(ratings.level_rating WHERE levels.level_id = ratings.level_id) FROM levels 

我知道我的SQL是有缺陷的,但我無法弄清楚如何在得到這個概念。我唯一能做的就是從整個收視表中返回一個平均值,這不是很有用。

從上面的概念有效,但語法出錯查詢理想的輸出將是:

level_id | level_rating 
     1| 3.34 
     2| 1.00 
     3| 4.54 

我主要的問題是我無法弄清楚如何使用每種響應行的level_id查詢已返回前。這就像我想使用佔位符...或別名...我真的不知道,這是非常令人沮喪的。我現在使用的解決方案是EPIC創可貼,並且只會長期引起我的問​​題...請幫助!

回答

2

如果您levelsInnoDB

SELECT l.level_id, COALESCE(AVG(level_rating), 0) 
FROM levels l 
LEFT JOIN 
     ratings r 
GROUP BY 
     l.id 

如果您的levels表爲MyISAM

SELECT l.level_id, 
     (
     SELECT COALESCE(AVG(level_rating), 0) 
     FROM rating r 
     WHERE r.level_id = l.level_id 
     ) 
FROM levels l 

子查詢爲MyISAM更有效,因爲它是基於堆和GROUP BY需要排序和/或物化。

+0

顯然我的表是MyISAM ...你的第二個查詢很好。我能夠削減大量不合理的代碼,將來自兩個單獨查詢的兩個數組合併爲一個! 我還會看到你的別名(這是合適的術語?)表名......這種抽象很有意義,我也可以在未來看到使用它。 – DirtyBirdNJ

1

您需要添加GROUP BY子句。試試這個:

SELECT levels.level_id 
     , AVG(ratings.level_rating) 
FROM  levels 
JOIN  ratings ON levels.level_id = ratings.level_id 
GROUP BY levels.level_id 

當您使用聚合函數(AVG,SUM,COUNT,MIN,MAX),您可以通過您選擇其他屬性需要組查詢。這就是爲什麼SELECT AVG(ratings.level_rating)在沒有GROUP BY的情況下工作的原因,但是嘗試選擇level_id也需要group by。

1

這給一試:

SELECT level_id, AVG(ratings.level_rating) 
FROM levels JOIN ratings USING(level_id) 
GROUP BY level_id 

注意level_id不會被引用到一個特定的表,因爲它是在的的USING部分使用加入

+1

我不知道'USING'命令。現在我想回到我的生活中,我已經花了很多時間打字PK/FK加入了漫長的道路。 – keithjgrant

+0

@keithjgrant我知道你的意思。如果你想更短,嘗試'NATURAL JOIN',儘管我有一些意想不到的結果。另外,如果你需要引用一個特定的表的列(通常在子查詢中),你必須將該名稱的每個引用都還原爲'ON',因爲'USING'使它無需表,因爲缺少更好的詞 – Tarka