web-dev-qa-db-ja.com

Moodleのコース登録のためのSQLクエリ

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つのアプローチの違いは何ですか?
よろしくお願いします。

9
d.yuk

最初のクエリは、ユーザーに割り当てられている役割に関係なく、コースに登録されているユーザーのリストを提供します(コースに登録されていても、役割がまったく割り当てられていない可能性があります)。

2番目のクエリは、コースレベルで役割5が割り当てられているすべてのユーザーを表示します。実際にコース自体に登録しなくても、コースレベルで役割を割り当てることは可能です(珍しいことですが)。

ただし、両方のクエリに欠陥があります。

ユーザーが複数の登録方法でコースに登録された場合、最初のクエリは重複した結果を返す可能性があります(通常ではありませんが可能です)。また、次のことも考慮に入れていません。

  • 登録プラグインはサイトレベルで無効になっている可能性があります
  • 登録プラグインはコースレベルで無効になっている可能性があります(アクティブな登録プラグインのみを見つけるには、「e.status = 0」を確認してください)
  • 登録には期限があります-ユーザーの登録が期限切れになっている可能性があります( 'ue.timeend = 0 OR ue.timeend> NOW()'をチェックして、期限切れでない登録のみを検索してください)

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

(そのクエリを広範囲に再確認していないことに注意してください-実行されますが、実際の登録と慎重に相互参照して、何も見逃していないことを確認する必要があります)。

14
davosmith

必要な場合は、コースに登録されている学生の数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で使用して、フロントページのコースリストに各コースの登録学生数を表示しました。

2
SaidbakR

次のコードは、すべてのコースのリストと、それぞれに登録されている学生の数を生成します。誰も登録していないコースがあるかどうかを確認するのに役立ちます。

私の答え :

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
user3809024

最初のクエリは、役割に関係なくすべての人に提供します-テーブルは登録のタイプを格納するために使用されます http://docs.moodle.org/26/en/Enrolment_plugins

2つ目は学生だけに提供されるので、もっと便利になります。

学生のみがコースに割り当てられているため、これらは同じ結果です。

コースに行ってユーザーを登録する場合。次に、ポップアップウィンドウの上部で、[ロールの割り当て] = [教師]を選択し、ユーザーを登録します。そのため、コースには生徒と教師がいます。

次に、クエリを再実行します。2番目のクエリには学生しかいないため、結果が少なくなります。

1
Russell England

個々のユーザーがサインアップしているコースを取得したい場合...

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はオプションであり、手動で編集可能なフィールドであることに注意してください。)

0
Yvonne Aburrow