我正在寻找适当的SQL查询来检索在某个课程中注册的所有学生,或者某个学生在Moodle上注册的所有课程.
我从互联网上找到了一些解决方案,其中大多数建议加入这些表:
context,role_assignments,course,user,role
但是当我查看数据库时,我发现有一个名为user_enrolments的表,在我看来,我可以通过加入以下表来获得结果:
user_enrolments,用户,课程,注册
例如,
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
和
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
(其中5是角色学生的id)
这两个查询为我提供了相同的结果集. (仅在一小组数据上测试)
所以我想问一下这两种方法有什么区别?
感谢您提前获得任何帮助.
解决方法
第一个查询为您提供了在课程中加入的用户列表,他们分配给他们的任何角色(可以在课程中加入课程并且根本没有分配任何角色).
第二个查询显示在课程级别为其分配了角色5的所有用户.有可能(虽然不寻常)在课程级别分配一个角色,而不是实际上在课程本身中.
但是,这两个查询都存在缺陷.
如果用户通过多种注册方法在课程中加入,则第一个查询可能会返回重复的结果(不寻常,但可能).它也没有考虑到以下因素:
>可以在站点级别禁用注册插件
>可以在课程级别禁用注册插件(检查’e.status = 0’以仅查找活动的注册插件)
>注册可能有时间限制 – 用户的注册可能已过期(检查’ue.timeend = 0或ue.timeend> NOW()’以仅查找未过期的注册)
第二个查询假定学生角色是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
(注意我没有仔细检查该查询 – 它运行,但你需要仔细交叉引用实际的注册,以检查我没有错过任何东西).