はじめに
Moodleを運用していると、こんな場面に出くわすことがあります。
「誰がどのコースをどこまで進んでいるか、一覧で確認したい」
「小テストは合格しているのか、修了証は発行されたのかも含めて把握したい」
標準のレポート機能を覗いてみると、コース別・ユーザー別にバラバラになっていて、「全員分を横断して一覧にするには……?」と詰まってしまうんですよね。
この記事では、Ad-hoc database queries というプラグインを使って、以下のような管理者向けレポートをMoodle上で作る手順を紹介します。
| ユーザー名 | 氏名 | コース名 | 登録日 | 経過日数 | 最終ログイン | 種別 | アクティビティ名 | 完了状態 | 完了日 | 修了証 |
|---|---|---|---|---|---|---|---|---|---|---|
| yamada | 山田太郎 | 情報セキュリティ基礎 | 2026-04-01 | 47 | 2026-05-10 | 小テスト | 確認テスト第1回 | 合格で完了 | 2026-04-15 | |
| yamada | 山田太郎 | 情報セキュリティ基礎 | 2026-04-01 | 47 | 2026-05-10 | ファイル | テキストPDF | 完了 | 2026-04-10 | |
| yamada | 山田太郎 | 情報セキュリティ基礎 | 2026-04-01 | 47 | 2026-05-10 | 修了証 | 修了証 | 完了 | 2026-04-20 | 発行済み |
動作確認はMoodle 4.5(セルフホスト)で行っています。
こんなときに使える
1. 月次の受講進捗報告
人事・研修担当者がマネージャーや経営層に対して月次で受講状況を報告するケース。「誰がどのコースをどこまで進んでいるか」をまとめた資料が必要になります。Moodle標準のレポートでは複数コース・複数ユーザーを横断した一覧が作りにくく、毎回手作業でデータをつなぎ合わせているケースも少なくないんじゃないでしょうか。
2. 全員受講が義務付けられている研修の管理
職場のハラスメント防止研修や情報セキュリティ教育など、コンプライアンス系の研修は「誰が未受講か」「小テストで合格しているか」「修了証が発行されているか」を一目で把握したいですよね。
3. 顧客企業への受講報告
研修サービスを提供している事業者が、クライアント企業に受講状況を報告するケース。「〇〇社の受講者全員の進捗をまとめてほしい」という依頼に対して、CSVで素早く出せると話が早いです。
4. コース改善のためのデータ分析
「どのアクティビティで多くの学習者が止まっているか」「小テストの合格率が低いモジュールはどれか」を把握して、コース設計の改善に活かすケース。こういう分析、意外とMoodle標準UIだとやりにくいんですよね。
5. eラーニング導入効果の検証
Moodleを導入してどの程度活用されているかを経営層に示すため、全体の完了率・ログイン頻度などをまとめたレポートが必要になるケース。
標準レポート・レポートビルダーでは作れない理由
「Moodleに最初からレポート機能がついているんじゃないの?」と思われるかもしれません。確かにあります。ただ、今回やりたいことには足りない部分があります。
Moodle標準のレポート機能
- 活動完了レポート(コース内):1コース内のアクティビティ別完了状況は確認できますが、複数コースをまたいだ集計はできません
- コース完了レポート:コース単位の完了状況のみで、アクティビティ別の詳細は出ません
- ログレポート:操作履歴は見られますが、完了状況との紐付けはできません
Moodle Workplaceのレポートビルダー
Moodle Workplaceには高機能なレポートビルダーが搭載されていて、「コース参加者」「発行された認定書」「プログラム」などのデータソースが使えます。ただし 「活動完了」(アクティビティ単位の完了状況)はデータソースとして提供されていません。コース全体の進捗率(%)は取れますが、「小テストAは合格、PDFは未閲覧」といったアクティビティ単位の詳細はレポートビルダーでは出せないんです。
つまり、「誰がどのアクティビティをどんな状態で完了しているか」を1画面で出す方法が、標準機能にはないというのが現状です。
Ad-hoc database queriesを選ぶ理由
プラグインの概要
Ad-hoc database queries(report_customsql)は、The Open University(英国)が開発・公開しているMoodleプラグインです。管理者がSQLクエリを登録しておくことで、Moodle管理画面から直接データベースに対してレポートを実行できます。
選ぶ理由
自由度が高い:レポートビルダーのUIで選べる列に限定されず、JOINやCASE文を使って必要な情報を自由に組み合わせられます。
無料で使える:OSSプラグインなので追加コストはかかりません。IntelliBoardなどの商用SaaSと比べると、ランニングコストの差は大きいです。
CSV出力に対応:レポート結果をCSVでダウンロードできるため、ExcelやGoogleスプレッドシートでの加工・共有が楽です。
Moodle 4.5・5.0対応:執筆時点(2026年5月)で最新のMoodleバージョンに対応しています。
できないこと
一方で、以下はこのプラグインではできません。
- INSERT・UPDATE・DELETEなどの書き込みクエリ(SELECTのみ)
- グラフ・チャートの描画
- リアルタイムダッシュボード
- ドリルダウン表示(行をクリックして詳細に入る、など)
あくまで「SQLで取ってきたデータをテーブル表示 + CSVダウンロード」というシンプルなツールです。それで十分なユースケースも多いですし、今回の目的にはちょうどよいです。
もし、結果をビジュアルに表現したいというニーズがある場合は、CSVで書き出しデータをMicrosoft Power BIなどのBIツールに読み込んで加工することを検討した方が良いでしょう。
インストール方法
前提条件
- Moodle 4.x または 5.x(セルフホスト環境)
- サイト管理者権限
Moodle Workplaceをお使いの方へ:SaaS版・セルフホスト版ともにAd-hoc database queriesは利用可能です。ただし修了証など一部のテーブル構造が標準Moodleと異なるため、SQLの書き換えが必要な箇所があります。詳細は記事末尾の「Moodle Workplaceを使う場合の補足」を参照してください。
方法A:Moodle管理画面からインストール
- 「サイト管理」 > 「プラグイン」 > 「プラグイン」をインストールする
- Moodle.org からzipをダウンロード
- zipファイルをアップロードしてインストール
方法B:サーバーに直接配置
cd /path/to/moodle/report
git clone https://github.com/timhunt/moodle-report_customsql.git customsql
その後、サイト管理 > 通知 にアクセスしてアップグレードを実行します。
インストール後に「サイト管理」 > 「レポート」のメニューに「アドホックデータベースクエリ」が表示されれば完了です。
基本的な使い方
クエリの作成
「サイト管理」>「レポート」> 「アドホックデータベースクエリ」を開いて、「新しいクエリを追加する」をクリックします。カテゴリ・クエリ名・説明・SQLを入力して保存するだけです。
SQLを書くときの2つのルール
このプラグインには、通常のSQLと違う点が2つあります。これを知らないとエラーが出るので最初に押さえておきましょう。
① テーブル名は {} で囲む
Moodleのテーブル名にはプレフィックス(デフォルトは mdl_)が付いています。プラグインがプレフィックスを自動補完するので、クエリ内では {} で囲んだプレフィックスなしの名前を使います。
-- ❌ これはエラーになる
SELECT * FROM mdl_user
-- ✅ こう書く
SELECT * FROM {user}
② LIMIT句は書かない
プラグインが自動でページング用のLIMITを付加するため、クエリ内にLIMITを書くとSQL構文エラーになります。
-- ❌ エラーになる
SELECT * FROM {user} LIMIT 10
-- ✅ LIMITなしで書く
SELECT * FROM {user}
動作確認用のシンプルなクエリ
まずこれで動くか確認してみてください。
SELECT
u.username AS ユーザー名,
u.lastname AS 姓,
u.firstname AS 名,
u.email AS メールアドレス,
FROM_UNIXTIME(u.lastlogin, '%Y-%m-%d') AS 最終ログイン日
FROM {user} u
WHERE u.deleted = 0
AND u.id > 1
ORDER BY u.lastname, u.firstname
目的のレポートを作る
使うテーブルの整理
今回のレポートで使うテーブルは以下のとおりです。
| テーブル | 用途 |
|---|---|
{user} |
ユーザー情報 |
{user_enrolments} |
コース登録情報 |
{enrol} |
登録方法 |
{course} |
コース情報 |
{course_modules} |
コース内のアクティビティ |
{modules} |
アクティビティの種別(quiz, resourceなど) |
{course_modules_completion} |
アクティビティ別完了状況 |
{quiz} / {resource} など |
アクティビティの名称取得 |
{customcert_issues} |
カスタム修了証の発行状況(mod_customcert プラグインが必要) |
completionstateの値について
{course_modules_completion} テーブルの completionstate カラムは以下の値を取ります。
| 値 | 意味 |
|---|---|
| NULL(レコードなし) | 未着手 |
| 0 | 未完了(開始したが条件未達) |
| 1 | 完了 |
| 2 | 合格で完了(小テストなどで合格点に達した) |
| 3 | 不合格 |
完成版SQL
SELECT
u.username AS ユーザー名,
CONCAT(u.lastname, u.firstname) AS 氏名,
c.fullname AS コース名,
FROM_UNIXTIME(ue.timecreated, '%Y-%m-%d') AS コース登録日,
DATEDIFF(NOW(), FROM_UNIXTIME(ue.timecreated)) AS 経過日数,
CASE WHEN u.lastlogin > 0
THEN FROM_UNIXTIME(u.lastlogin, '%Y-%m-%d')
ELSE ''
END AS 最終ログイン日,
CASE m.name
WHEN 'quiz' THEN '小テスト'
WHEN 'resource' THEN 'ファイル'
WHEN 'url' THEN 'URL'
WHEN 'page' THEN 'ページ'
WHEN 'feedback' THEN 'アンケート'
WHEN 'customcert' THEN '修了証'
WHEN 'assign' THEN '課題'
ELSE m.name
END AS 種別,
COALESCE(
q.name,
r.name,
p.name,
f.name,
fb.name,
assign.name,
scorm.name,
url.name,
cc.name
) AS アクティビティ名,
CASE cmc.completionstate
WHEN 0 THEN '未完了'
WHEN 1 THEN '完了'
WHEN 2 THEN '合格で完了'
WHEN 3 THEN '不合格'
ELSE '未着手'
END AS 完了状態,
CASE WHEN cmc.timemodified > 0
THEN FROM_UNIXTIME(cmc.timemodified, '%Y-%m-%d')
ELSE ''
END AS 完了日,
CASE WHEN ci.id IS NOT NULL
THEN '発行済み'
ELSE ''
END AS 修了証
FROM {user} u
JOIN {user_enrolments} ue ON ue.userid = u.id
JOIN {enrol} e ON e.id = ue.enrolid
JOIN {course} c ON c.id = e.courseid
JOIN {course_modules} cm ON cm.course = c.id AND cm.completion > 0
JOIN {modules} m ON m.id = cm.module
LEFT JOIN {course_modules_completion} cmc
ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
LEFT JOIN {quiz} q ON m.name = 'quiz' AND q.id = cm.instance
LEFT JOIN {resource} r ON m.name = 'resource' AND r.id = cm.instance
LEFT JOIN {page} p ON m.name = 'page' AND p.id = cm.instance
LEFT JOIN {forum} f ON m.name = 'forum' AND f.id = cm.instance
LEFT JOIN {feedback} fb ON m.name = 'feedback' AND fb.id = cm.instance
LEFT JOIN {assign} assign ON m.name = 'assign' AND assign.id = cm.instance
LEFT JOIN {scorm} scorm ON m.name = 'scorm' AND scorm.id = cm.instance
LEFT JOIN {url} url ON m.name = 'url' AND url.id = cm.instance
LEFT JOIN {customcert} cc ON m.name = 'customcert' AND cc.id = cm.instance
LEFT JOIN {customcert_issues} ci
ON ci.customcertid = cm.instance
AND ci.userid = u.id
AND m.name = 'customcert'
WHERE u.deleted = 0
AND u.id > 1
AND u.username != 'admin'
ORDER BY u.username, c.fullname, cm.section, cm.id
SQLのポイント解説
完了条件が設定されたアクティビティだけを対象にする
JOIN {course_modules} cm ON cm.course = c.id AND cm.completion > 0
cm.completion > 0 により、Moodleの活動完了設定で「完了条件」が設定されているアクティビティのみを対象にします。完了条件が未設定のアクティビティは除外されます。
未着手のユーザーも表示する
LEFT JOIN {course_modules_completion} cmc
ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
LEFT JOIN を使うことで、まだアクティビティを開始していない(cmc にレコードがない)ユーザーも NULL → '未着手' として表示できます。コース登録はしたが何もしていない人もちゃんと出てきます。
アクティビティ名の取得
Moodleはアクティビティの種別ごとに別テーブルを持っています({quiz}、{resource}、{page} など)。それぞれをLEFT JOINして、COALESCE で最初に見つかった値をアクティビティ名として使います。
修了証アクティビティの注意点
このSQLの修了証機能は Custom certificate(mod_customcert)プラグインを使用しています。Moodle標準には修了証機能が含まれていないため、事前に Moodle.org からインストールしておく必要があります。
customcert(カスタム修了証)アクティビティがレポートに表示されるには、アクティビティの完了条件に「証明書を受け取ったら完了とみなす」を設定する必要があります。設定がないと cm.completion = 0 となり、このクエリの対象外になってしまいます。
設定手順:
- コースの編集モードをオン
- 修了証アクティビティの編集 → 「完了条件」
- 「証明書を受け取る」にチェックを入れて保存
絞り込みたいときは
特定コースに絞る場合はWHERE句に追加します。
AND c.id = 対象コースID
-- または
AND c.shortname = 'コースの短縮名'
コーホートで絞る場合はJOINを追加します。
JOIN {cohort_members} cohm ON cohm.userid = u.id AND cohm.cohortid = 対象コーホートID
生成AIでSQLを書いてもらうTIPS
Moodle固有のテーブル構造を把握しながらSQLを書くのは、最初はなかなかハードルが高いです。ClaudeなどのAIを使うと効率よく書けます。実際、この記事のSQLもほぼClaudeと対話しながら作りました。
プロンプトのコツ
Moodle固有のルールを最初に伝える
Moodleのreport_customsqlプラグイン用のSQLを書いてください。
以下のルールがあります:
- テーブル名は{}で囲む(例:{user}、{course})
- LIMIT句は書かない
- MariaDB(MySQL互換)で動作すること
欲しい列を具体的に伝える
以下の列を持つレポートを作りたいです:
- ユーザー名・氏名
- コース名・登録日・経過日数
- アクティビティ名・種別・完了状態・完了日
- 修了証の発行状況
エラーが出たらそのまま貼る
エラーメッセージをそのままChatに貼ると原因と修正版SQLを返してくれます。「どのエラーメッセージをどう読めばいいか分からない」状態でも使えるのが便利なところです。
段階的に作る
一度にすべての列を含む複雑なSQLを作ろうとせず、まず動く最小構成を作ってから列を1つずつ追加していくと問題の切り分けがしやすくなります。
よくあるエラーと対処法
| エラー | 原因 | 対処 |
|---|---|---|
Table 'xxx.mdl_tablename' doesn't exist |
テーブル名をそのまま書いている |
{tablename} の形式に変更 |
near 'LIMIT 0, 2' |
クエリ内にLIMIT句を書いている | LIMIT句を削除 |
Table doesn't exist |
プラグインが未インストール | 対象プラグインのインストールを確認 |
| アクティビティ名がNULLになる | 対応テーブルのLEFT JOINが漏れている | 該当アクティビティ種別のJOINを追加 |
まとめ
| 比較項目 | 標準レポート | レポートビルダー(Workplace) | Ad-hoc database queries |
|---|---|---|---|
| アクティビティ別完了 | △(1コース内のみ) | ❌ | ✅ |
| 複数コース横断 | ❌ | ✅ | ✅ |
| 修了証発行状況 | ❌ | ✅ | ✅ |
| CSV出力 | △ | ✅ | ✅ |
| カスタマイズ性 | ❌ | △ | ✅ |
| SQL知識が必要 | 不要 | 不要 | 必要(AIで代替可) |
「誰がどのアクティビティをどんな状態で完了しているか」を1つのレポートで確認したいなら、Ad-hoc database queriesが現時点では最も現実的な選択肢です。SQLはAIを使って効率よく書けるので、SQL経験が少ない方でも十分活用できると思います。
Moodle Workplaceを使う場合の補足
Ad-hoc database queriesはMoodle Workplaceでも利用できますが、以下の点に注意が必要です。
修了証のテーブルが異なる:Moodle Workplaceでは修了証に tool_certificate モジュールが使われており、テーブル名やJOINの書き方が標準Moodleと異なります。上記SQLをそのまま使うとエラーが出るので、環境に合わせた書き換えが必要です。
テーブルの存在確認方法:
-- モジュール名の一覧確認
SELECT id, name FROM {modules} ORDER BY name
-- 特定テーブルの存在確認(エラーが出なければ存在する)
SELECT id FROM {tool_certificate_issues}
Workplaceのバージョンや構成によってテーブル名が異なる場合があるため、環境ごとに確認しながら進めるのがおすすめです。
参考リンク
- Ad-hoc database queries - Moodle.org
- GitHub - timhunt/moodle-report_customsql
- Moodle Database schema - MoodleDocs
- Custom certificate plugin - Moodle.org
※ この記事は Zenn (rublix) にも投稿しています。





