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.

Example dates for one student in one course An example timeline from enrollment through the last course visit, last assignment submission, last finished quiz and withdrawal. Your policy decides which date is the last date of attendance. Example: one student in one course Enrolled Last course visit Course Access Last assignment submitted Assignment Submissions Last quiz finished Quiz Attempts Withdrawn Enrollments and Withdrawals Your policy decides which date is the last date of attendance
Example dates for one student in one course. Your policy decides which date to use.

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.

sql
-- 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 seeWhat to do
No learners appearOne 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 missingCheck the loaded enrollment history and withdrawal dates.
A date is blankThere is no activity of that kind in the loaded data.

Next guides

Failing students across courses with Brightspace Data Sets: final grades below a pass markHow to join Brightspace Data Sets: keys and a worked query