Moodleで、特定のコースに登録されているすべての学生、または特定の学生が登録しているすべてのコースを取得するための適切なSQLクエリを探していました。
私はインターネットからいくつかの解決策を見つけました、そしてそれらのほとんどはこれらのテーブルに参加することを提案します:
コンテキスト、role_assignments、コース、ユーザー、ロール
しかし、データベースを見ると、user_enrolments
という名前のテーブルがあることがわかり、次のテーブルを結合することで結果を得ることができたようです。
ser_enrolments、user、course、enrol
例えば、
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です)
これらの2つのクエリにより、[〜#〜] same [〜#〜]一連の結果が得られます。 (少数のデータセットでのみテスト済み)
では、2つのアプローチの違いは何ですか?
よろしくお願いします。
最初のクエリは、ユーザーに割り当てられている役割に関係なく、コースに登録されているユーザーのリストを提供します(コースに登録されていても、役割がまったく割り当てられていない可能性があります)。
2番目のクエリは、コースレベルで役割5が割り当てられているすべてのユーザーを表示します。実際にコース自体に登録しなくても、コースレベルで役割を割り当てることは可能です(珍しいことですが)。
ただし、両方のクエリに欠陥があります。
ユーザーが複数の登録方法でコースに登録された場合、最初のクエリは重複した結果を返す可能性があります(通常ではありませんが可能です)。また、次のことも考慮に入れていません。
2番目のクエリは、学生の役割がID 5であると想定しています(また、学生の役割に基づいて、使用されている他の役割がないことも前提としています)。通常、追加のクエリを使用して、テーブル 'mdl_role'の 'student'ロールのIDを確認してからその値を使用するか、最後の数行を次のように変更します。
JOIN mdl_role r ON r.id = ra.roleid AND r.shortname = 'student'。
2番目のクエリも「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
(そのクエリを広範囲に再確認していないことに注意してください-実行されますが、実際の登録と慎重に相互参照して、何も見逃していないことを確認する必要があります)。
必要な場合は、コースに登録されている学生の数。 enrollment api を使用するだけで実現できます。ここでの秘密鍵は、withcapability
ロールのみが持つcount_enrolled_users()
関数にStudent
パラメーターを提供することです。例えば:
$context = context_COURSE::instance($course->id);
count_enrolled_users($context,'mod/assignment:submit')
ここで、mod/assignment:submit
は学生だけが実行できる機能であるため、返されるint番号には、コースに登録されている教師などの他の一般的な役割は含まれません。
上記のMoodle3.1のコードをテーマrenderer.php
で使用して、フロントページのコースリストに各コースの登録学生数を表示しました。
次のコードは、すべてのコースのリストと、それぞれに登録されている学生の数を生成します。誰も登録していないコースがあるかどうかを確認するのに役立ちます。
私の答え :
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
最初のクエリは、役割に関係なくすべての人に提供します-テーブルは登録のタイプを格納するために使用されます http://docs.moodle.org/26/en/Enrolment_plugins
2つ目は学生だけに提供されるので、もっと便利になります。
学生のみがコースに割り当てられているため、これらは同じ結果です。
コースに行ってユーザーを登録する場合。次に、ポップアップウィンドウの上部で、[ロールの割り当て] = [教師]を選択し、ユーザーを登録します。そのため、コースには生徒と教師がいます。
次に、クエリを再実行します。2番目のクエリには学生しかいないため、結果が少なくなります。
個々のユーザーがサインアップしているコースを取得したい場合...
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
はオプションであり、手動で編集可能なフィールドであることに注意してください。)