Moodle上的课程注册的SQL查询

时间:2014-03-04 02:22:53

标签: sql database moodle

我正在寻找正确的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 结果集。 (仅在一小组数据上测试)

所以我想问一下这两种方法有什么不同?
感谢您提前提供任何帮助。

5 个答案:

答案 0 :(得分:14)

第一个查询会为您提供一个在课程中加入的用户列表,他们分配给他们的任何角色(可以在课程中加入课程并且根本没有分配任何角色)。

第二个查询显示在课程级别分配了角色5的所有用户。有可能(虽然不寻常)在课程级别分配一个角色,但实际上并没有在课程中加入。

但是,这两个查询都存在缺陷。

如果用户通过多种注册方法在课程中加入,则第一个查询可能会返回重复的结果(不寻常,但可能)。它也没有考虑到以下内容:

  • 可以在网站级别停用注册插件
  • 可以在课程级别禁用注册插件(检查'e.status = 0'以仅查找有效的注册插件)
  • 注册可能有时间限制 - 用户的注册可能已过期(请检查'ue.timeend = 0或ue.timeend> NOW()'以仅查找未过期的注册)

第二个查询假定学生角色是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是可选且可手动编辑的字段。)