我正在寻找正确的SQL查询,以便在 Moodle 上检索所有注册某个课程的学生,或者某个学生注册的所有课程。
我从互联网上找到了一些解决方案,其中大多数建议加入这些表格:
上下文,role_assignments,课程,用户,角色
但是当我查看数据库时,我发现有一个名为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是角色student
的ID)
这两个查询为我提供了 SAME 结果集。 (仅在一小组数据上测试)
所以我想问一下这两种方法有什么不同?
感谢您提前提供任何帮助。
答案 0 :(得分:14)
第一个查询会为您提供一个在课程中加入的用户列表,他们分配给他们的任何角色(可以在课程中加入课程并且根本没有分配任何角色)。
第二个查询显示在课程级别分配了角色5的所有用户。有可能(虽然不寻常)在课程级别分配一个角色,但实际上并没有在课程中加入。
但是,这两个查询都存在缺陷。
如果用户通过多种注册方法在课程中加入,则第一个查询可能会返回重复的结果(不寻常,但可能)。它也没有考虑到以下内容:
第二个查询假定学生角色是id 5(并且还有没有其他角色,基于学生角色,正在使用中)。我通常会使用额外的查询来检查表'mdl_role'中'student'角色的id,然后使用该值,或者将最后几行更改为以下内容:
加入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
(注意我没有广泛地仔细检查该查询 - 它运行,但您需要仔细交叉引用实际注册以检查我没有遗漏任何内容。)
答案 1 :(得分:2)
以下代码会生成所有课程的列表,以及每个课程中注册的学生人数。有助于了解您是否有任何没有人注册的课程。
我的回答:
SELECT cr.SHORTNAME,
cr.FULLNAME,
COUNT(ra.ID) AS enrolled
FROM `MDL_COURSE` cr
JOIN `MDL_CONTEXT` ct
ON ( ct.INSTANCEID = cr.ID )
LEFT JOIN `MDL_ROLE_ASSIGNMENTS` ra
ON ( ra.CONTEXTID = ct.ID )
WHERE ct.CONTEXTLEVEL = 50
AND ra.ROLEID = 5
GROUP BY cr.SHORTNAME,
cr.FULLNAME
ORDER BY `ENROLLED` ASC
答案 2 :(得分:2)
如果需要,注册学生的课程数。可以简单地使用enrollment api来实现。这里的密钥是向仅withcapability
角色所具有的count_enrolled_users()
函数提供Student
参数。例如:
$context = context_COURSE::instance($course->id);
count_enrolled_users($context,'mod/assignment:submit')
此处mod/assignment:submit
是一项只有学生能够做到的能力,因此返回的int号码不会包括其他常见角色,例如在课程中注册的教师。
我在主题renderer.php
中使用了Moodle 3.1的上述代码,在头版的课程列表中显示了每个课程的注册学生数。
答案 3 :(得分:1)
第一个查询将为您提供所有人,无论他们的角色如何 - 该表用于存储注册类型 - http://docs.moodle.org/26/en/Enrolment_plugins
第二个只会给你学生 - 所以会更有用。
结果相同,因为只有学生被分配到课程中。
如果你去一门课程并注册用户。然后在弹出窗口的顶部选择assign roles = teacher并注册用户。因此,在课程中,您将拥有学生和教师
然后重新运行查询,第二个查询的结果会更少,因为它只会有学生。
答案 4 :(得分:0)
如果您想获得个人用户注册的课程......
SELECT c.id, c.shortname, c.summary, c.idnumber
FROM mdl_course c
JOIN mdl_enrol en ON en.courseid = c.id
JOIN mdl_user_enrolments ue ON ue.enrolid = en.id
WHERE ue.userid = '12345'
AND c.idnumber LIKE "blah%"
(最后一行是可选的,可用于过滤特定类型的课程。请注意idnumber
是可选且可手动编辑的字段。)