1

我正在尝试列出学生及其测试效率。在MySql数据库中我有表

users- 与学生同桌

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

courses- 课程表

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

questions- 每门课程的问题表。行 course_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

示例: Joe 和 Anna 被邀请参加课程 1 和课程 2,Marry 和 Max 被邀请参加课程 1。Joe 参加了课程 1 但没有参加课程 2,Marry 什么也没做,Max 参加了课程 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

示例: Joe 完成了第一门课程的 3 个问题。请注意,他没有完成该课程的所有问题,而且其中一个是不正确的。

麦克斯做的所有问题都正确,安娜完成了第一道菜的所有问题(一半不正确)和第二道菜的一半(全部正确)

我需要一个查询,其中包含学生姓名、完成课程的百分比、他们完成的课程的正确答案百分比(不是所有课程)以及按这些百分比对学生进行排序的可能性。像这样的东西:

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

这样的事情甚至可能吗?我需要在表中添加更多行来进行此查询吗?

4

3 回答 3

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_*

于 2012-04-22T14:48:00.633 回答
4

在这里您可以找到表模式和示例数据以及查询结果。MichaelRushton 有完美的答案,但我认为 course_stats 必须是 LEFT 加入。因为如果学生有 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
于 2012-04-22T15:06:45.667 回答
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 之外添加百分号,因为它在那里更加优雅,它会给 mysql 查询增加不必要的复杂性。

于 2012-04-23T09:43:49.493 回答