See every grade a Moodle learner earned — across all courses, even after they're unenrolled
Moodle's gradebook is per-course, so there's no one screen that shows a single learner's whole record — and unenrolled learners drop out of the gradebook entirely. Here's the SQL to pull it yourself, and the free report we built so you don't have to.
Someone from your registrar's office asks a simple-sounding question: "What did this learner score — in everything?"
In Moodle, that is not a one-click answer. The gradebook is built per course: to see a learner's totals you open each course's grade report, one at a time, and copy the numbers into a spreadsheet by hand. If the learner has taken twelve courses, that's twelve screens. And if they were ever unenrolled — expired cohort, finished contract, seasonal cleanup — they won't appear in those grade reports at all, because the live grade rows were deleted the moment they were removed.
We ran into this constantly supporting a busy training platform: current staff, past staff, contractors who'd rolled off, all needing their records pulled for audits and re-certification. Doing it by hand didn't scale. So we wrote a report that answers the question directly — and because tools like this are how we introduce ourselves, we're releasing it free. This post is the honest version: what the gap actually is, how to pull the data yourself with SQL, and where the plugin picks up.
The gap
Why there's no "all of a learner's grades" screen in core Moodle
Moodle's data model puts every grade in mdl_grade_grades, keyed to a grade item that belongs to exactly one course. The gradebook UI reads that table per course. The user's profile page gives you an "Grades overview" link, but it still walks you course by course — there's no consolidated, filterable, exportable table of "this person, every course, one view." For a handful of learners you click through it. For a cohort, or for anyone who's left, you can't.
Unenrolment makes it worse. A full unenrol deletes the learner's rows from mdl_grade_grades — so they vanish from every course grade report — but archives each deleted row into mdl_grade_grades_history first. The grade still exists; nothing in the core UI will show it to you. (We wrote up that mechanism in detail in Moodle grades gone after re-enrolment? They're not.)
The manual way
Pulling a learner's cross-course grades with SQL
If you just need the answer once and you have database access, you don't need any plugin. This query lists a single learner's course-total grade in every course, reading the live gradebook. The course total is the grade item with itemtype = 'course':
SELECT c.shortname, c.fullname,
gg.finalgrade, gi.grademax,
ROUND(100 * gg.finalgrade / NULLIF(gi.grademax,0), 1) AS percent
FROM mdl_grade_items gi
JOIN mdl_grade_grades gg ON gg.itemid = gi.id
JOIN mdl_course c ON c.id = gi.courseid
WHERE gi.itemtype = 'course'
AND gg.userid = ? -- the learner
AND gg.finalgrade IS NOT NULL
ORDER BY c.fullname;
That covers everyone still enrolled. To also catch courses the learner was unenrolled from — where the live row is gone but the value survives in history — union the latest history row per course:
SELECT c.shortname, latest.finalgrade, gi.grademax
FROM mdl_grade_items gi
JOIN mdl_course c ON c.id = gi.courseid
JOIN (
SELECT ggh.itemid, ggh.finalgrade
FROM mdl_grade_grades_history ggh
JOIN (
SELECT itemid, MAX(timemodified) AS tm
FROM mdl_grade_grades_history
WHERE userid = ? AND finalgrade IS NOT NULL
GROUP BY itemid
) newest ON newest.itemid = ggh.itemid
AND newest.tm = ggh.timemodified
) latest ON latest.itemid = gi.id
WHERE gi.itemtype = 'course'
AND gi.id NOT IN (
SELECT itemid FROM mdl_grade_grades
WHERE userid = ? AND finalgrade IS NOT NULL
);
This is genuinely enough for a one-off. But notice what it doesn't give you: a name search (you need the userid already), an item-by-item breakdown, certificates, completion, time-on-task, cohort filtering, or an export your registrar can open. Rebuild all of that by hand every time someone asks, and you've written a report. So we did.
The tool
Grade Lookup — a free report that answers the whole question
Grade Lookup (report_gradelookup) is a Moodle site report. Once installed it lives under Site administration → Reports → Grade Lookup, and it's a single search box for people, not databases. Type a name or email — current, past, or unenrolled — and you get that learner's grade in every course, a click-through to the item-by-item breakdown, their certificates, and a one-click Excel download. Filter by course or cohort (by name or ID) and it turns into a cohort summary: learner count, average grade, completion, certificates issued, time spent.
Open a learner and you get their record: course totals across everything, each one clickable into the item-by-item grade breakdown (recovered from history where the live grade was purged), plus any certificates they've been issued with verification codes.
What it does
The whole feature set, plainly
- Find any learner — by name or email, including current, past, and fully unenrolled learners (their grades are recovered from history, so they still appear).
- Filter by course or cohort — search by name or ID (type
AML-C12), pick more than one, and add an optional active-time date window. - Read the summary — for whatever you've filtered to, a strip of tiles shows learner count, average grade (with median and range), completion, certificates, and active time.
- Open a learner — their grade in every course, each expandable to the item-by-item breakdown, plus certificates with verification links.
- Export to Excel — one click produces a workbook: a summary sheet and the full learner list. CSV is available too.
Grades are shown as plain percentages. The report deliberately doesn't colour them pass/fail, because every course sets its own passing mark — a green "82%" would be a lie in a course that requires 90.
Built to Moodle's standards
Safe to put on a production site
A report that reads grade history and personal data has to be trustworthy, so this one is built to the plugin-review bar rather than as a quick hack:
- Read-only. It never writes to your database — no new tables, no schema, no scheduled tasks. Uninstalling leaves nothing behind.
- Access-gated. A dedicated capability,
report/gradelookup:view(manager level, flaggedRISK_PERSONAL), controls who can open it — so it's not exposed to anyone with a login. - Privacy-clean. It ships a Moodle Privacy API provider declaring it stores no personal data of its own; it only displays grades, grade history, and certificates that already exist.
- Injection-safe and current. Every query is parameterised, every output escaped, and it's tested against Moodle 4.3 LTS through 5.0 using stable core APIs.
We had it audited dimension by dimension — structure, security, privacy, performance, and search UX — against Moodle's official developer standards before releasing it.
Get it
Installing Grade Lookup
It installs like any Moodle plugin, no server shell required:
- Download the plugin ZIP (link goes on the plugins page as the Moodle Marketplace listing goes live).
- In Moodle: Site administration → Plugins → Install plugins, upload the ZIP, and install from the ZIP file.
- Run the upgrade when prompted, then find it under Site administration → Reports → Grade Lookup.
Requirements: Moodle 4.3 or newer. Certificate display uses mod_customcert if you have it, and is skipped cleanly if you don't. As always, try it on a staging site first.
If you need a report core Moodle doesn't have
Grade Lookup exists because a client needed a question answered that Moodle couldn't answer out of the box, and building the report properly was cheaper than doing it by hand forever. That's most custom reporting: a specific cross-section of your data — grades, completion, certificates, attendance, SCORM tracking — that no core screen quite gives you. Assembling those is routine Moodle development work for us, and the good ones become free releases like this one. If you keep re-answering the same question by clicking through twelve screens, tell us what it is — we'll reply within one business day.
Quick answers
Questions people ask about this
Can you see all of a student's grades across every course in Moodle?
Not from one core screen. Moodle's gradebook is per-course, and the user profile links out to each course grade report one at a time. There is no built-in page that lists a single learner's course totals across every course they have taken. You either open each course in turn, run SQL against mdl_grade_grades, or install a report plugin that consolidates it — such as our free Grade Lookup report.
Why do a learner's grades disappear after you unenrol them?
A full unenrolment deletes the learner's rows from mdl_grade_grades, the live table the gradebook reads, so they vanish from every course grade report. Moodle archives each deleted row into mdl_grade_grades_history first, so the values still exist — but no core screen shows them. Grade Lookup reads both tables, so unenrolled and past learners still appear.
What is the report_gradelookup plugin?
Grade Lookup (report_gradelookup) is a free, GPLv3 Moodle site report from Sternfast. It adds a search under Site administration ▸ Reports ▸ Grade Lookup where you find any learner by name or email — current, past, or unenrolled — and see their grade in every course, an item-by-item breakdown, their certificates, and summary metrics for any course or cohort. Results export to Excel. It is read-only and stores no data of its own.
Does Grade Lookup work on unenrolled and deleted-enrolment learners?
Yes. Where a learner's live grade rows were removed by unenrolment, Grade Lookup recovers the course total from mdl_grade_grades_history, so past learners still show up in search and their grades still display. It reads history rather than recomputing, so it works even where gradebook items were purged.
How do I export a learner grade report from Moodle to Excel?
Core gradebook exports are per-course. To export a cross-course view — a filtered set of learners with their course totals and summary metrics — Grade Lookup has a one-click Download (Excel) button that produces a workbook with a summary sheet and the full learner list. A CSV export is also available.
Is Grade Lookup safe to install on a production Moodle site?
It is designed to be. The report is read-only, adds no database tables, runs no scheduled tasks, and is gated behind its own capability (report/gradelookup:view, manager level, marked RISK_PERSONAL). It ships a Privacy API provider declaring it stores no personal data of its own, all queries are parameterised, and it is tested on Moodle 4.3 through 5.0. As with any plugin, install it on a staging site first.