2012-04-20 58 views
1

我試圖列出學生及其測試效率。 在MySql數據庫我有表MySql查詢 - 計算行數和百分比

users - 表與學生

id | name 
_________ 
1 | Joe 
2 | Marry 
3 | Max 
4 | Anna 
---------- 

courses - 表課程

id | name 
_____________ 
1 | Course 1 
2 | Course 2 
---------- 

questions - 以每門課程的問題表。行cours_id表示這當然這個問題屬於

id | cours_id | question 
_________________________________ 
1 | 1  | Course 1 - question 1 
2 | 1  | Course 1 - question 2 
3 | 1  | Course 1 - question 3 
4 | 1  | Course 1 - question 4 
5 | 2  | Course 2 - question 1 
6 | 2  | Course 2 - question 2 
7 | 2  | Course 2 - question 3 
8 | 2  | Course 2 - question 4 

cours_invitations - 每個學生得到邀請爲一療程。行user_id顯示被邀請參加課程的用戶的ID。 cours_id代表學生應該做的課程的ID。 當行狀態的值爲0時,表示學生沒有開始課程(待定),如果它的值爲1,表示學生已經開始(或完成)。

id | user_id | cours_id | status 
________________________________ 
1 | 1  | 1  | 1 
2 | 1  | 2  | 0 
3 | 2  | 1  | 0 
4 | 3  | 1  | 1 
5 | 4  | 1  | 1 
6 | 4  | 2  | 1 

例子:喬和安娜被邀請做課程1和課程2,結婚和Max被邀請做唯一的辦法1.喬做了場1,但當然不是2,結婚沒做什麼和馬克思課程1

courses_stats - 是學生已經完成的課程的問題的統計數字。狀態代表答案的準確性。 0代表錯誤答案,1代表正確答案。

id | user_id | question_id | status 

___________________________________ 
1 | 1  | 1   | 1 
2 | 1  | 2   | 1 
3 | 1  | 3   | 0 
4 | 2  | 1   | 1 
5 | 2  | 2   | 1 
6 | 2  | 3   | 1 
7 | 2  | 4   | 1 
8 | 4  | 1   | 1 
9 | 4  | 2   | 1 
10 | 4  | 3   | 0 
11 | 4  | 4   | 0 
12 | 4  | 5   | 1 
13 | 4  | 6   | 1 

例子:喬的確從他並沒有這樣做從該課程所有問題的第一course.Notice 3個問題,那種是不正確。

馬克斯做了所有的問題,正確的和安娜做了所有的問題,從第一場(一半是不正確的),另一半來自第二期培訓班(正確)

我需要sudents名稱,成品課程perecentage,百分比查詢他們所做的那些課程的正確答案(並非全部課程)以及按這些百分比命令學生的可能性。 事情是這樣的:

name | completed courses | completed questions 
______________________________________________ 
Max |100%    |100% 
Anna |100%    |50% 
Joe |50%    |50% 
Marry |0%     |0% 

是這樣甚至可能嗎?這個查詢在表格中是否需要更多行?

回答

4

我想這應該是你所需要的:

SELECT 
    users.name, 
    CONCAT(COUNT(
     DISTINCT CASE 
     WHEN cours_invitations.status = 1 THEN 
      cours_invitations.id 
     ELSE 
      NULL 
     END 
    )/COUNT(
     DISTINCT cours_invitations.id 
    ) * 100, '%') AS completed_courses, 
    CONCAT(COUNT(
     DISTINCT CASE 
     WHEN courses_stats.status = 1 THEN 
      courses_stats.id 
     ELSE 
      NULL 
     END 
    )/COUNT(DISTINCT questions.id) * 100, '%') AS completed_questions 
FROM 
    users 
LEFT JOIN cours_invitations ON cours_invitations.user_id = users.id 
LEFT JOIN questions ON cours_invitations.cours_id = questions.cours_id 
AND cours_invitations.status = 1 
LEFT JOIN courses_stats ON users.id = courses_stats.user_id 
GROUP BY 
    users.id 
ORDER BY 
    completed_courses DESC, 
    completed_questions DESC 

作爲一個問題丟回給你,爲什麼表名叫做cours_*而非course_*

+0

快速的答案和很好的查詢。 – 2012-04-22 15:08:20

+0

謝謝。原來有點不對。需要'LEFT JOIN's就像你在你的答案何況還要對'ON'一個額外的一部分,以確保其只計算用戶已經開始的課程(例如問題,Joe的完成問題,需要爲50%,而不是25% ) – MichaelRushton 2012-04-22 15:15:19

+0

完美,你是對的。你可能想添加'ifnull(...,0)AS completed_questions',因爲結婚的競爭問題將爲空,否則顯示0可能會更好。 – 2012-04-22 15:28:59

4

在這裏你可以找到表模式和樣本數據,以及查詢結果。 MichaelRushton有完美的答案,但我認爲course_stats必須是左連接。 因爲如果學生有cours_invitations但沒有course_stats,則該查詢不會返回該用戶。

http://sqlfiddle.com/#!2/019dc/1

SELECT 
    users.name, 
    COUNT(
     DISTINCT CASE 
     WHEN course_invitations.status = 1 THEN 
      course_invitations.id 
     ELSE 
      NULL 
     END 
    )/COUNT(
     DISTINCT course_invitations.id 
    ) * 100 AS completed_courses, 
    COUNT(
     DISTINCT CASE 
     WHEN courses_stats.status = 1 THEN 
      courses_stats.id 
     ELSE 
      NULL 
     END 
    )/COUNT(DISTINCT questions.id) * 100 AS completed_questions 
FROM users 
INNER JOIN course_invitations ON course_invitations.user_id = users.id 
INNER JOIN questions ON course_invitations.cours_id = questions.cours_id 
LEFT JOIN courses_stats ON users.id = courses_stats.user_id 
GROUP BY 
    users.id 

結果:

NAME COMPLETED_COURSES COMPLETED_QUESTIONS 
Joe 50 25 
Marry 0 100 
Max 100 0 
Anna 100 50 
0

我猜你的意思是 「正確答案的百分比」。好吧,巧妙地使用count(distinct if(..))結構,您可以避免使用不同的group-by子句進行復雜的子查詢。例如,該代碼

count(distinct if(cours_invitations.status and courses_stats.status, 
         NULL, questions.id)) 

計數,其中條件cours_invitations.status and courses_stats.status被滿足的(不同)問題的數量。使用這一招,整個查詢是簡單而優雅的,因爲這:

select users.name, 
    count(distinct if(cours_invitations.status, 
         NULL, 
         cours_invitations.cours_id)) 
     /count(distinct cours_invitations.cours_id) 
     * 100 as courses_completed, 
    count(distinct if(cours_invitations.status and courses_stats.status, 
          NULL, 
          questions.id)) 
     /count(distinct if(cours_invitations.status, 
           NULL, 
           questions.id)) 
     * 100 as correct_answers 
from users 
    left join cours_invitations on users.id = cours_invitations.user_id 
    left join questions using (cours_id) 
    left join courses_stats on users.id = courses_stats.user_id 
           and questions.id = courses_stats.question_id 
group by users.id 
order by correct_answers 

我建議增加外的MySQL百分號,因爲它是更優雅那裏,這會增加uneccessary複雜MySQL查詢。