Analyze completion and score data with a short SQL query and report it honestly.
Why it matters
Training teams sit on a lot of data: enrollments, completions, quiz scores, survey answers, time spent. Stakeholders ask for it constantly ("What percentage of the support team has finished?"). Being able to pull and summarize that data yourself, and to explain what it does and does not show, makes you far more effective than waiting for a report someone else builds. You do not need to be a programmer: a few lines of SQL go a long way.
Common training metrics
| Metric | What it tells you | Watch out for |
|---|---|---|
| Enrollments | Reach | Says nothing about learning |
| Completion rate | Share of enrolled learners who finished | Easy to game with "viewed" completion rules |
| Assessment score | Performance on the test at the end | Depends on test quality |
| Pre/post gain | Change from before to after | Needs the same or equivalent tests |
| Time to proficiency | How fast people reach the standard | Needs a clear standard |
| On-the-job measures | Behavior and results (Kirkpatrick 3 and 4) | Many other causes |
Reading training data with SQL
Many LMSs let you export reports or query a reporting database. A typical export has one row per learner per course. Here is a small table called enrollments:
| learner | team | course | completed | pre_score | post_score |
|---|---|---|---|---|---|
| Ana | Support | Incident basics | 1 | 55 | 85 |
| Ben | Support | Incident basics | 0 | 60 | (empty) |
completed is 1 for finished and 0 for not finished. post_score is empty (NULL) for people who have not finished.
Four SQL ideas cover most training reports:
SELECT course, -- 1. choose columns
COUNT(*) AS enrolled, -- 2. count rows in each group
ROUND(100.0 * SUM(completed) / COUNT(*), 1) AS completion_pct
FROM enrollments
GROUP BY course -- 3. one row per course
ORDER BY completion_pct DESC; -- 4. sort the result
COUNT(*)counts learners in each course.SUM(completed)adds up the 1s, which is the number who finished. Multiplying by100.0(not100) makes the division a decimal rather than a whole number.AVG(...)gives an average and ignores empty (NULL) values. That meansAVG(post_score - pre_score)is the average gain of the people who finished, because the others have no post score.WHERE team = 'Support'would filter to one team before grouping.
Interpreting the numbers
Suppose the query shows:
| course | enrolled | completion_pct | avg_gain |
|---|---|---|---|
| Escalation paths | 5 | 80.0 | 22.5 |
| Incident basics | 6 | 66.7 | 26.3 |
| Writing summaries | 5 | 40.0 | 7.5 |
Questions a good trainer asks:
- Why is "Writing summaries" completion so low? Is it at a busy time, too long, or broken? Look at where people stop.
- Is the small gain a problem with the course or the test? A pre-test that is already high leaves little room to improve (a ceiling effect).
- Survivorship: average gain covers only completers. If the people who struggled dropped out, the gain looks better than it really is.
- Small numbers: with five learners, one person changes the completion rate by 20 points. Report the counts alongside the percentages.
- Completion is not competence. A high completion rate with a weak test tells you little; connect to Level 3 and 4 measures where you can.
Reporting to stakeholders
- Lead with the question the stakeholder cares about ("Are new engineers ready for the rotation?"), not with every metric.
- Show counts and percentages together.
- Compare with a baseline or target.
- Say what the data cannot show, and what you will do next.
- Use simple charts: a bar chart of completion by course beats a pie chart or a dense table.
Privacy and ethics
Learning data is personal data. Share individual results only with people who need them, aggregate where possible, follow your organization's privacy rules (and laws such as GDPR), and be careful about using training scores in performance reviews without telling learners in advance. People answer practice quizzes honestly only when it is safe to be wrong.
Common mistakes
- Reporting completion as if it were learning.
- Dividing whole numbers and getting 0 instead of 66.7.
- Ignoring that averages skip empty values.
- Percentages from tiny groups with no counts.
- Sharing named results widely.
Quick recap
- Know what each metric shows and its trap.
COUNT,SUM,AVG,GROUP BYandORDER BYanswer most training questions.AVGignores NULL, which affects who is included.- Report counts with percentages, compare with a baseline, protect learner data.
Try it
On the Do tab, finish a query that reports completion and average score gain per course.