After a withdrawal, the registrar or financial aid office may ask for the student's last date of attendance. Many schools look this up one course at a time. Across every course, this query lists students whose latest loaded enrollment action is a withdrawal within your dates, with their last visit, submitted assignment and finished quiz.
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.
Load Enrollments and Withdrawals, Course Access, Assignment Submissions, Quiz Attempts, Users, Organizational Units and Role Details.
Run the last date of attendance query
Change the first day on line 8 and the last day on line 9. The range includes both dates as full days in Coordinated Universal Time (UTC). The query uses each student's latest loaded enrollment action, even if it happened after the range ended, so students who later re-enrolled are left out. If an enrollment and a withdrawal have the same time, the student counts as enrolled. The query also needs an earlier enrollment row to find the student's role; students without one do not appear.
-- Edit the role names on the RoleName IN line to choose who counts as a learner.
WITH learner_roles AS (
SELECT DISTINCT RoleId
FROM RoleDetails
WHERE RoleName IN ('Student')
),
Settings AS (
SELECT DATE '2025-09-01' AS FirstDay,
DATE '2025-12-31' AS LastDay
), Actions AS (
SELECT UserId, OrgUnitId, Action, EnrollmentDate,
ROW_NUMBER() OVER (PARTITION BY UserId, OrgUnitId
ORDER BY EnrollmentDate DESC,
CASE WHEN Action = 'Enroll' THEN 0 ELSE 1 END, LogId DESC) AS Position
FROM EnrollmentsAndWithdrawals
), Enrollments AS (
SELECT UserId, OrgUnitId, RoleId,
ROW_NUMBER() OVER (PARTITION BY UserId, OrgUnitId
ORDER BY EnrollmentDate DESC, LogId DESC) AS Position
FROM EnrollmentsAndWithdrawals
WHERE Action = 'Enroll'
), Withdrawals AS (
SELECT Actions.UserId, Actions.OrgUnitId, Actions.EnrollmentDate AS WithdrawnOn
FROM Actions
JOIN Enrollments ON Enrollments.UserId = Actions.UserId AND Enrollments.OrgUnitId = Actions.OrgUnitId
JOIN learner_roles ON learner_roles.RoleId = Enrollments.RoleId
CROSS JOIN Settings
WHERE Actions.Position = 1 AND Enrollments.Position = 1 AND Actions.Action = 'Unenroll'
AND CAST(Actions.EnrollmentDate AS DATE) BETWEEN Settings.FirstDay AND Settings.LastDay
), CourseVisits AS (
SELECT UserId, OrgUnitId, CAST(MAX(DayAccessed) AS DATE) AS LastCourseAccess
FROM CourseAccess
GROUP BY UserId, OrgUnitId
), Submissions AS (
SELECT SubmitterId AS UserId, OrgUnitId, MAX(LastSubmissionDate) AS LastSubmission
FROM AssignmentSubmissions
WHERE SubmitterType = 'User'
AND COALESCE(TRY_CAST(IsDeleted AS BOOLEAN), false) = false
GROUP BY SubmitterId, OrgUnitId
), Quizzes AS (
SELECT UserId, OrgUnitId, MAX(TimeCompleted) AS LastQuizAttempt
FROM QuizAttempts
WHERE COALESCE(TRY_CAST(IsDeleted AS BOOLEAN), false) = false
GROUP BY UserId, OrgUnitId
)
SELECT DISTINCT W.UserId, Users.FirstName, Users.LastName, W.OrgUnitId,
Courses.Name AS CourseName, W.WithdrawnOn,
CourseVisits.LastCourseAccess, Submissions.LastSubmission, Quizzes.LastQuizAttempt
FROM Withdrawals W
JOIN Users ON Users.UserId = W.UserId
JOIN OrganizationalUnits Courses ON Courses.OrgUnitId = W.OrgUnitId
LEFT JOIN CourseVisits ON CourseVisits.UserId = W.UserId AND CourseVisits.OrgUnitId = W.OrgUnitId
LEFT JOIN Submissions ON Submissions.UserId = W.UserId AND Submissions.OrgUnitId = W.OrgUnitId
LEFT JOIN Quizzes ON Quizzes.UserId = W.UserId AND Quizzes.OrgUnitId = W.OrgUnitId
WHERE Courses.Type = 'Course Offering'
ORDER BY W.UserId, W.OrgUnitId;The query counts people whose role is named Student in Role Details. To count other roles, edit the RoleName IN list near the top, for example ('Student', 'Learner'). Names must match exactly. Joins use RoleId, so two roles with the same name both count, and a renamed role follows its current name.
Submitted work counts even if ungraded. To include only graded work, append AND IsGraded = true to line 38 for assignments and line 43 for quizzes. Group assignments are excluded because the submitter is a group.
Course Access records browser visits as local days, not times. Other dates are UTC.
Read the last dates per course
Fictional sample data: all 8 rows.
| UserId | FirstName | LastName | OrgUnitId | CourseName | WithdrawnOn | LastCourseAccess | LastSubmission | LastQuizAttempt |
|---|---|---|---|---|---|---|---|---|
| 1 | Fictional | Same person | 100 | Same course | 2025-11-01T12:00 | 2025-10-01 | 2025-10-01T10:00 | 2025-10-01T11:00 |
| 1 | Fictional | Same person | 200 | Same course | 2025-11-01T12:00 | 2025-10-02 | 2025-10-02T10:00 | 2025-10-02T11:00 |
| 2 | Fictional | Same person | 100 | Same course | 2025-11-01T12:00 | 2025-10-03 | 2025-10-03T10:00 | 2025-10-03T11:00 |
| 2 | Fictional | Same person | 200 | Same course | 2025-11-01T12:00 | 2025-10-04 | 2025-10-04T10:00 | 2025-10-04T11:00 |
| 3 | Fictional | Person 3 | 100 | Same course | 2025-11-01T12:00 | null | null | null |
| 4 | Fictional | Person 4 | 100 | Same course | 2025-11-01T12:00 | null | null | 2025-10-08T11:00 |
| 5 | Fictional | Person 5 | 100 | Same course | 2025-09-01T00:00 | null | null | null |
| 6 | Fictional | Person 6 | 100 | Same course | 2025-12-31T23:59 | null | null | null |
null means no activity of that kind in the loaded data. IDs separate same-name students and courses. Financial aid offices often need the last academic activity, such as a submitted assignment or quiz, not only the last visit. Your policy decides which date to send as the last date of attendance.
When it goes wrong
| What you see | What to do |
|---|---|
| No learners appear | One possible cause is that no role in Role Details matches the role names list. Check the exact role names in Role Details and edit the list at the top of the query. A Rowseta session limited to one course cannot read Role Details, so sign in directly. |
| A student is missing | Check the loaded enrollment history and withdrawal dates. |
| A date is blank | There is no activity of that kind in the loaded data. |