Full and differential data sets describe different versions of records. If you simply stack their rows, duplicate rows can repeat learners and inflate counts. Keep the newest row for each key, then use this check to find repeated enrollment keys.

Where the data comes from: Brightspace Data Sets, the CSV extracts Brightspace publishes in Data Hub. This is not a built-in Brightspace report or screen. Rowseta syncs these data sets for you, or your administrator can download the extracts for your own SQL tool.

Run this query

Choose where to run it

  • In Rowseta: open Reports > New report and paste the query into the SQL editor on the Query tab. Sync the data sets listed below first.
  • In your own setup: load your Data Hub extracts into your own SQL tool, one table per data set, named without spaces (User Enrollments becomes UserEnrollments), after applying differentials to the fulls. Another SQL tool may need small changes to these queries.

A free Rowseta Desktop app is coming soon.

This query needs User Enrollments. The reference explains its columns and the key used in the check below.

Check full and differential data for duplicates

With weekly fulls and daily differentials, a full extract gives the starting records. A differential contains changes, so the same record can appear again with newer values. Simply putting all those rows together would count repeated versions as separate records. That would make enrollment totals hard to interpret and could repeat a learner in a report.

Rowseta combines fulls and differentials during sync, with the newest row winning for a matching key. In your own setup, apply those changes yourself before running this query. A raw union of full plus differential rows is what this check catches.

Stacked extracts repeat the same enrollment row The Course 100, User 910 enrollment appears in the first full, changes in the Day 3 differential and repeats in the next full. Of these three stacked rows, keep the newest from Week 2 and drop the older two. Day 5 has Course 200, User 910, a different key that is kept separately. One enrollment, three appearances Default: full weekly, differential daily Week 1 full Day 3 differential Day 5 differential Week 2 full Course 100, User 910 Version 1 Enrolled Sep 2 Course 100, User 910 Version 2 Role changed Course 200, User 910 Different course key Kept separately Course 100, User 910 Version 2 repeated Role changed Stacked together: Course 100, User 910 Week 1 full: version 1, Enrolled Sep 2 dropped Day 3 differential: version 2, Role changed dropped Week 2 full: version 2, Role changed kept: newest row Keep the newest row for each OrgUnitId + UserId
The same enrollment row repeats across a full and its differentials; keep only the newest row for each OrgUnitId and UserId.

For User Enrollments, the key is the pair OrgUnitId and UserId: the course or other organizational unit, together with the user. One user can have enrollments in several courses. That is expected, because each course gives the pair a different value. Counting UserId alone would mistake those separate enrollments for duplicates.

Run the complete query in your chosen tool. No value needs replacing. The query groups rows by the two key columns, counts the rows in each group and returns only groups whose count is greater than one.

sql
-- No values need changing for UserEnrollments.
-- Its catalog key is the combination of OrgUnitId and UserId.
SELECT OrgUnitId, UserId, COUNT(*) AS DuplicateCount
FROM UserEnrollments
GROUP BY OrgUnitId, UserId
HAVING COUNT(*) > 1
ORDER BY OrgUnitId, UserId;

The HAVING COUNT(*) > 1 line is why an empty result is the expected outcome here. Groups with exactly one row do not appear. This check is specific to the User Enrollments key; other data sets can have different keys (check each data set reference), so changing only the table name would not make it a valid general duplicate check.

This also does not compare the text of every field or check whether every expected enrollment is present. It answers one question about the combined rows: does any organizational-unit and user pair appear more than once? Keep that narrow meaning when you use the result alongside your other checks.

Read the duplicate enrollment check

This fictional sample data returns no rows. Rowseta shows:

This report has no rows in the synced data.

Other SQL tools show an empty result.

This means there are no duplicate keys in the combined User Enrollments data for that sample; it does not mean that there are no enrollments. If your result contains rows instead, each returned pair has more than one row, and DuplicateCount tells you how many.

When it goes wrong

What you seeWhat to do
An empty resultThis is the expected result when no User Enrollments key appears more than once.
The same user is in several coursesThat is not a duplicate key. Compare OrgUnitId and UserId together.
The query returns duplicate pairsReview the returned OrgUnitId and UserId pairs. The count describes repeated keys in the combined data, not repeated names.

Next guides

Brightspace course enrollment report: every course in a termHow to join Brightspace Data Sets: keys and a worked query