d.y*_*yuk 9 sql database moodle
我正在寻找适当的SQL查询来检索在某个课程中注册的所有学生,或者某个学生已经注册的所有课程,在Moodle上.
我从互联网上找到了一些解决方案,其中大多数建议加入这些表:
context,role_assignments,course,user,role
但是当我查看数据库时,我发现有一个名为的表user_enrolments,在我看来,我可以通过加入以下表来获得结果:
user_enrolments,user,course,enroll
例如,
SELECT u.id, c.id
FROM mdl_user u
INNER JOIN mdl_user_enrolments ue ON ue.userid = u.id
INNER JOIN mdl_enrol e ON e.id = ue.enrolid
INNER JOIN mdl_course c ON e.courseid = c.id
Run Code Online (Sandbox Code Playgroud)
和
SELECT u.id, c.id
FROM mdl_user u
INNER JOIN mdl_role_assignments ra ON ra.userid = u.id
INNER JOIN mdl_context ct ON ct.id = ra.contextid
INNER JOIN mdl_course c ON c.id = ct.instanceid
INNER JOIN mdl_role r ON r.id = ra.roleid
WHERE r.id = 5
Run Code Online (Sandbox Code Playgroud)
(其中5是角色的id student)
这两个查询给出了相同的结果集.(仅在一小组数据上测试)
所以我想问一下这两种方法有什么区别?
感谢您提前获得任何帮助.
dav*_*ith 14
第一个查询为您提供了在课程中加入的用户列表,他们分配给他们的任何角色(可以在课程中加入课程并且根本没有分配任何角色).
第二个查询显示在课程级别为其分配了角色5的所有用户.有可能(虽然不寻常)在课程级别分配一个角色,而不是实际上在课程本身中被编入.
但是,这两个查询都存在缺陷.
如果用户通过多种注册方法在课程中加入,则第一个查询可能会返回重复的结果(不寻常,但可能).它也没有考虑到以下内容:
第二个查询假定学生角色是id 5(并且还有没有其他角色,基于学生角色,正在使用中).我通常会使用额外的查询来检查表'mdl_role'中'student'角色的id,然后使用该值,或者将最后几行更改为以下内容:
JOIN mdl_role r ON r.id = ra.roleid AND r.shortname ='student'.
第二个查询也无法检查'contextlevel' - 可能有多个具有相同实例ID的上下文(因为它可能包含课程ID 5,课程类别ID 5,用户ID 5等) - 所以您需要检查找到的上下文是否为"课程"上下文(contextlevel = 50).
查询都不会检查已暂停的用户或已删除的用户(但是,对于已删除的用户,它们应该在删除它们时自动从所有课程中删除).
一个完全完整的解决方案(在大多数情况下可能过于复杂)会将两个查询组合在一起,以检查用户是否已被编入并分配了学生的角色而未被暂停:
SELECT DISTINCT u.id AS userid, c.id AS courseid
FROM mdl_user u
JOIN mdl_user_enrolments ue ON ue.userid = u.id
JOIN mdl_enrol e ON e.id = ue.enrolid
JOIN mdl_role_assignments ra ON ra.userid = u.id
JOIN mdl_context ct ON ct.id = ra.contextid AND ct.contextlevel = 50
JOIN mdl_course c ON c.id = ct.instanceid AND e.courseid = c.id
JOIN mdl_role r ON r.id = ra.roleid AND r.shortname = 'student'
WHERE e.status = 0 AND u.suspended = 0 AND u.deleted = 0
AND (ue.timeend = 0 OR ue.timeend > NOW()) AND ue.status = 0
Run Code Online (Sandbox Code Playgroud)
(注意我没有仔细检查该查询 - 它运行,但你需要仔细交叉引用实际的注册,以检查我没有错过任何东西).