Redshift tables: learning, courses & assessments

Learning plans, SCORM, course progress and assessments. This is where most compliance and certification reporting comes from, and it is also where the reconciliation traps live — read the two warnings below before you build anything. Expand any table to see what it holds and every field available through the connector.

How these tables fit together

From

To

Join

learning_plans

learning_plan_items

learning_plan_id = learning_plans.id

learning_plan_items

content / SCORM / event

item_id filtered by item_type

learning_plans

assigned users

via learning_plan_assigned_memberships or audience_learning_plan_assignments

user_course_progresses

plan or SCORM course

course_id filtered by course_type

user_scorm_reporting_data

contents

content_id = contents.id

assessment_results

assessment_templates

assessment_template_id = assessment_templates.id

questions

question_sets

question_set_id = question_sets.id

answers

questions

question_id = questions.id

question_choice_answers

answers / question_choices

join table on both IDs

Two assignment tables, and they do not mean the same thing. learning_plan_assigned_memberships assigns a plan via a community membership; audience_learning_plan_assignments assigns it to an individual user as part of an audience. Universal Analytics' Learning Plan Audience counts records of learning plan assignments — if you use only one of these two tables, your completion rate denominator will be wrong. Check which assignment method your organisation actually uses, and if it is both, union them and de-duplicate by user.

SCORM courses inside learning plans get counted twice. This is documented Fuse behaviour, not a bug. user_course_progresses uses course_type to distinguish a learning plan record from a standalone SCORM record, so a SCORM course that sits inside a learning plan produces two rows — one for the plan and one for the SCORM course in its own right. Always filter or group by course_type when counting completions, or your totals will inflate.

Learning plans

learning_plans — the plan definition

Structures and manages user development, supporting training, compliance and personalised learning. It defines a set of courses, activities or goals users are expected to complete as part of their training, onboarding or professional development.

Fuse uses it to: organise and assign learning paths to individuals or groups; track progress and completion of required training; support reporting and analytics for managers and administrators; and let users view, manage and complete their assigned plans.

For reporting: using_audience_enabled tells you which assignment model this plan uses — that determines which of the two assignment tables you should be counting. community_id links the plan to a learning plan community, which is the basis for the "current community members" audience metric. visibility and visibility_for govern who can see the plan at all.

Field

Role

id

Primary key

company_id

Tenant key

title

Plan name

slug

URL identifier

description

Attribute

community_id

Foreign key → communities.id

using_audience_enabled

Assignment model — determines which assignment table applies

visibility

Access setting

visibility_for

Access setting

available_notification_enabled

Notification setting

report_download_enabled

Permission flag

asset_id

Asset reference

price

Commercial attribute

created_at

Timestamp

updated_at

Timestamp

learning_plan_items — what is inside a plan

Structures and manages the components of learning plans, supporting organised training, progress tracking and personalised learning. It defines each item — a course, module, assessment or activity — that users must complete as part of a plan.

Fuse uses it to: organise and sequence the steps users follow in a plan; track progress and completion of each item; let admins build, edit and manage structured learning paths; and support reporting, notifications and compliance tracking.

For reporting: counting rows per plan gives you the item count, which is the denominator behind plan progress percentages. position gives the intended sequence — join it against progress data to find the exact step where learners stall. Filter item_type before joining to content, SCORM or events.

Field

Role

id

Primary key

learning_plan_id

Foreign key → learning_plans.id

item_id

Polymorphic ID — the item itself

item_type

Polymorphic type — filter on this first

type

Item category

position

Sequence in the plan

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

learning_plan_assigned_memberships — assignment via community membership

Organises and monitors which users are assigned to learning plans, supporting training management and progress tracking. It acts as a join table linking memberships to learning plans, indicating who is expected to complete a particular set of courses or activities.

Fuse uses it to: manage and track user assignments for training, onboarding or development; display assigned plans to users and monitor progress; support reporting on plan completion; and enable notifications and reminders.

Note: this assigns via membership_id, not user_id — you need a hop through memberships to reach the person. If a user leaves the community, the membership goes and so does the assignment, which is one reason historical completion records can outlive current assignments.

Field

Role

id

Primary key

learning_plan_id

Foreign key → learning_plans.id

membership_id

Foreign key → memberships.id

company_id

Tenant key

created_at

Timestamp — assignment date

updated_at

Timestamp

audience_learning_plan_assignments — assignment to individual users

Organises and monitors which groups of users are assigned to learning plans, supporting scalable training management and progress tracking. It links learning plans to audiences, indicating which users are expected to complete a particular set of courses or activities.

Fuse uses it to: assign plans to groups of users for training, onboarding or compliance; track progress and completion at audience level; support reporting for managers on group training status; and enable notifications and reminders for assigned audiences.

Note: despite the "audience" name, the exposed field list resolves to a direct user_id — no hop through memberships needed. This is the cleaner of the two assignment tables to work with. Use it where learning_plans.using_audience_enabled is set.

Field

Role

id

Primary key

learning_plan_id

Foreign key → learning_plans.id

user_id

Foreign key → users.id

company_id

Tenant key

created_at

Timestamp — assignment date

updated_at

Timestamp

Course progress

user_course_progresses — the main learning fact table

Monitors and reports user advancement in courses, supporting personalised learning, compliance and progress tracking. It records how far a user has advanced, including completion status, scores and other progress metrics.

Fuse uses it to: display course progress on dashboards and profile pages; support reporting and analytics for managers and administrators; trigger notifications, reminders or unlock next steps; and enable compliance tracking for mandatory training or certification.

Start here for almost all learning reporting. Universal Analytics builds Not Started, In Progress, Completed Courses, Learning Plan Completion Rate and their percentage variants by counting records in this table and filtering on the learning status. completion_count is important for recurring or expiring training — it increments each time a user completes the course again, so a single row can represent several completions over time. progress holds only the most recent progress score, not a history.

Field

Role

id

Primary key

user_id

Foreign key → users.id

course_id

Polymorphic ID — plan or SCORM course

course_type

Polymorphic type — filter to avoid double-counting

status

Learning status — not started, in progress, completed

progress

Latest progress score only

completion_count

Times completed — key for recurring training

course_started

Timestamp — first started

course_finished

Timestamp — completion date

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

scorm_courses — SCORM package definitions

No description was provided in the source. Added here for orientation. Defines each SCORM package uploaded into Fuse, including its asset location, launch behaviour, approval requirements and certificate settings.

For reporting: state tells you whether the package is live. certificate_enabled identifies courses that issue certificates, which is usually the set that matters for compliance reporting. The three *_approval_required flags mirror the event approval model — SCORM courses can also require sign-off before a user can start them, which explains gaps between assignment and first activity. provider distinguishes packages by their authoring source.

Field

Role

id

Primary key

company_id

Tenant key

uuid

Stable external identifier

state

Publication status

provider

Authoring source

asset_uid

Package file reference

index_path

Launch file path

launch_in_new_window

Display setting

certificate_enabled

Certification flag

signature_image_uid

Certificate asset reference

creator_approval_required

Approval workflow flag

manager_approval_required

Approval workflow flag

specified_approval_required

Approval workflow flag

approver_id

Foreign key → users.id

price

Commercial attribute

created_at

Timestamp

updated_at

Timestamp

user_scorm_reporting_data — detailed SCORM attempt data

Records and reports user activity in SCORM courses, supporting progress tracking, compliance and detailed analytics. It records user progress, scores, completion status and other SCORM-specific data for each course attempt.

Fuse uses it to: track progress and performance for compliance and reporting; display completion status, scores and activity history; support analytics, certification and regulatory requirements; and enable troubleshooting by storing detailed SCORM interaction data.

This is the only place you get genuine time spent data. session_time is the duration of a single session; total_time is cumulative across the course. attempt_id means this table holds a row per attempt, so unlike user_course_progresses you can analyse repeat attempts and score improvement properly. suspend_data is the SCORM bookmark blob — it is opaque and has no reporting value, so exclude it from your import to save space.

Field

Role

id

Primary key

user_id

Foreign key → users.id

content_id

Foreign key → contents.id

attempt_id

Attempt identifier — one row per attempt

score

Score achieved

status

Completion status

session_time

Duration of this session

total_time

Cumulative time on the course

suspend_data

SCORM bookmark blob — exclude from import

started_at

Timestamp — attempt start

completed_at

Timestamp — attempt completion

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

fuse_completeness_course_expiry_settings — expiry and recurrence rules

Manages course expiry policies and completion rules, supporting compliance, certification and ongoing learning requirements. It stores the configuration for how and when courses expire, and what rules apply to completion tracking.

Fuse uses it to: determine when a course should be considered expired for a user or group; enforce retake or renewal requirements for compliance or certification; trigger notifications when a course nears expiry; and support reporting on completion and expiry status.

Essential for any compliance dashboard. Without this table you can report who has completed something, but not who is still currently compliant. Combine validness_period with user_course_progresses.course_finished to calculate an expiry date per user, then compare against today for a live compliance position. reset_period governs recurring training cycles, and notification_periods tells you when reminders fire — useful for measuring whether reminders actually drive renewals.

Field

Role

id

Primary key

course_id

Polymorphic ID — the course

course_type

Polymorphic type — filter on this first

expiry_state

Whether expiry is active

validness_period

How long a completion stays valid

reset_period

Recurrence cycle length

deadline_state

Whether a deadline applies

deadline

Fixed completion deadline

max_deadline_period_after_start

Relative deadline rule

max_deadline_period_after_availability

Relative deadline rule

notification_periods

When reminders are sent

overdue_reminder_strategy

Escalation rule

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

apprentice_course_progresses — apprenticeship progress

Monitors and reports apprentice advancement in courses, supporting personalised learning, mentorship and progress tracking throughout apprenticeship programmes. It records how far each apprentice has advanced in a specific course, including completion status and performance metrics.

Fuse uses it to: display course progress to apprentices and their mentors or managers; support reporting and analytics for apprenticeship programmes; trigger notifications, reminders or unlock next steps based on progress; and enable compliance tracking for required training or certification.

Expected data: an apprentice reference, a course reference, progress metrics such as completion percentage, status, score and last-accessed date, plus standard timestamps.

No field list is available for this table in the source. The description above tells you what it holds conceptually, but the exact column names exposed through the connector are not documented here. Inspect the table directly in Redshift before building against it, and let your Fuse contact know if you need this documented properly.

Assessments

The assessment model runs: assessment_templates defines the assessment → question_sets groups its questions → questions are the questions → question_choices are the available options → answers are what users submitted → question_choice_answers links a submitted answer to the choice selected. assessment_results holds the outcome of each attempt, and user_assessment_stats is a pre-aggregated summary per user.

assessment_templates — the assessment definition

Enables Fuse to create, manage and reuse assessment formats, supporting scalable and consistent delivery. It defines the structure and configuration of an assessment — questions, settings and layout — so new assessments can be generated quickly from a template.

Fuse uses it to: let admins and content creators design reusable assessment formats; streamline creation of new assessments by copying template data; ensure consistency across the application; and support versioning and updates to assessment formats.

For reporting: pass_score is the threshold that determines pass or fail, so keep it in your model rather than hardcoding a number. max_number_of_attempts and days_for_attempts_limit constrain retakes — worth showing alongside attempt counts so a low retake rate is not misread as disengagement when it is actually a cap. assessable_id + assessable_type link the assessment to whatever it is attached to.

Field

Role

id

Primary key

company_id

Tenant key

name

Assessment name

type

Assessment type

assessable_id

Polymorphic ID — what it is attached to

assessable_type

Polymorphic type — filter on this first

pass_score

Pass threshold

questions_count

Denormalised counter

max_value

Maximum achievable score

formula

Scoring rule

autocalculate

Scoring setting

max_number_of_attempts

Retake limit

days_for_attempts_limit

Retake window

force_to_answer_all_questions

Completion rule

ordering

Question order rule

instructions

Display text

agreement

Display text

start_button_label

Display text

finish_button_label

Display text

go_back_target

Navigation setting

publish_topic_questions_on

Scheduling rule

publish_topic_questions_on_enrollment_day

Scheduling rule

notify_participants_via

Notification setting

notify_participants_on_question_availability

Notification setting

notification_time_span

Notification setting

notification_text

Notification setting

settings

Serialised settings

created_at

Timestamp

updated_at

Timestamp

assessment_results — the outcome of each attempt

Records, manages and analyses the outcomes of assessments, supporting user progress tracking and organisational reporting. It tracks each user's results for a specific assessment — a quiz, test or survey.

Fuse uses it to: display assessment outcomes to users and administrators; support analytics, reporting and progress tracking; determine eligibility for certifications, next steps or rewards; and enable filtering and searching of performance across users or groups.

For reporting: this is your assessment fact table — one row per attempt, so count rows for attempts and distinct user_id for people. state carries the pass, fail or incomplete outcome that most Universal Analytics assessment metrics filter on. main_result_id identifies the primary result where an assessment produces several, so filter on it to avoid double-counting. Filter deleted_at is null.

Field

Role

id

Primary key

user_id

Foreign key → users.id

assessment_template_id

Foreign key → assessment_templates.id

assessment_template_type

Template category

assignment_id

Foreign key — the assignment

main_result_id

Primary result reference — filter to avoid double-counting

score

Score achieved

state

Outcome — passed, failed, incomplete

result_data

Serialised result detail

questions_count

Denormalised counter

deleted_at

Soft delete

company_id

Tenant key

created_at

Timestamp — attempt date

updated_at

Timestamp

user_assessment_stats — pre-aggregated results per user

Tracks and reports user performance on assessments efficiently, supporting analytics, progress monitoring and personalised feedback. It holds aggregated data for each user related to their assessment activity — scores, completion rates and progress metrics.

Fuse uses it to: quickly display user progress and performance in dashboards or reports; support analytics and insights for users, managers or administrators; enable filtering, ranking and tracking based on results; and optimise queries by storing pre-calculated stats.

Use this for headline assessment reporting; use assessment_results when you need attempt-level detail. One row per user per assessment template, with completed, uncompleted and expired counts already calculated. Universal Analytics' Assessment Completion Rate counts records here where completed attempts is greater than zero, divided by Topic Audience. Note that expired_count exists here but not in assessment_results — this is the only place you get expiry.

Field

Role

id

Primary key

user_id

Foreign key → users.id

assessment_template_id

Foreign key → assessment_templates.id

completed_count

Completed attempts

uncompleted_count

Incomplete attempts

expired_count

Expired attempts — only available here

completion_at

Timestamp — completion date

completion_score

Score at completion

completion_result

Outcome at completion

completion_percentage

Progress percentage

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

Questions & answers

question_sets — groups of questions

Organises and manages groups of questions, supporting flexible assessment design and efficient content reuse. It defines a set of questions that can be presented together as part of an assessment or activity.

Fuse uses it to: organise questions into reusable sets for different assessments or activities; let admins and content creators manage groups of questions efficiently; support randomised or structured delivery in quizzes and surveys; and enable reporting on question set performance and usage.

For reporting: included and formula_number affect how a set contributes to the overall assessment score — check these before assuming every question in a template counts equally. group and add_to_group support grouped scoring, which is how competency-area breakdowns are built.

Field

Role

id

Primary key

assessment_template_id

Foreign key → assessment_templates.id

name

Set name

questions_count

Denormalised counter

included

Scoring inclusion flag

formula_number

Scoring weight reference

group

Grouped scoring reference

add_to_group

Grouped scoring flag

position

Display sequence

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

questions — the questions themselves

Manages and delivers interactive content, supporting assessment creation, user engagement and data collection. It defines each question that can be presented to users, including its text, type and configuration.

Fuse uses it to: build assessments, quizzes and surveys by linking questions to templates; display questions to users and collect responses; support analytics, reporting and content management; and let admins create, edit, organise and reuse questions.

For reporting: type determines how you should analyse the responses — multiple choice, scale and free text all behave differently. value is the question's weight in scoring. topic_id links questions to topics, which is what makes topic-level competency reporting possible. Filter deleted_at is null.

Field

Role

id

Primary key

question_set_id

Foreign key → question_sets.id

topic_id

Foreign key → topics.id

body

Question text

type

Question format — drives how to analyse it

representation_type

Display format

value

Scoring weight

position

Display sequence

asset_id

Asset reference

settings

Serialised settings

deleted_at

Soft delete

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

answers — the available answers for a question

Shows the available answers for a specific question. Linked to questions by question_id, it contains the answer body, the value of the selected answer, timestamps, and any assets such as images attached to that question.

For reporting: correct is the flag behind every Universal Analytics correct-answer metric. Note that the metrics distinguish three states — correct, incorrect and incomplete, where an answer has been marked as neither — so do not assume "not correct" means "wrong". numerator and denominator support fractional or partial-credit scoring. Filter deleted_at is null.

Field

Role

id

Primary key

question_id

Foreign key → questions.id

body

Answer text

correct

Correctness flag — may also be neither

value

Score value

numerator

Partial-credit scoring

denominator

Partial-credit scoring

asset_id

Asset reference

hash_key

Internal identifier

deleted_at

Soft delete

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

question_choices — what a user selected, and the score

Manages and displays answer options for questions, supporting interactive assessments and accurate response tracking. It defines each selectable choice for a question so users can pick from predefined options.

Fuse uses it to: present answer options for multiple-choice questions in assessments, quizzes and surveys; record which choices users select; support grading, analytics and reporting; and let admins create, edit and organise choices.

For reporting: despite the name, the exposed fields make this the per-response record — it carries assessment_result_id, score, text_answer and working_out, which is where free-text and show-your-working responses live. non_applicable flags responses deliberately marked N/A, and these must be excluded from scoring averages or you will understate performance. Filter deleted_at is null.

Field

Role

id

Primary key

question_id

Foreign key → questions.id

assessment_result_id

Foreign key → assessment_results.id

score

Score for this response

text_answer

Free-text response

working_out

Show-your-working response

non_applicable

N/A flag — exclude from score averages

hash_keys

Internal identifier

deleted_at

Soft delete

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp

question_choice_answers — links a response to the answer chosen

Tracks and analyses user selections for multiple-choice questions, supporting assessment delivery, reporting and organisational insight. It is a join table linking a user's answer (answer_id) to a specific choice (question_choice_id).

Fuse uses it to: store and retrieve user responses for multiple-choice questions; support grading, analytics and reporting on results; ensure data integrity by enforcing uniqueness of choice and answer pairs; and associate responses with companies for organisational reporting.

For reporting: this is the table that lets you build answer-distribution analysis — which specific wrong answer people pick most often for a given question. That is the most actionable assessment insight available in the model, because it points directly at the content gap or the badly worded question. Filter deleted_at is null.

Field

Role

id

Primary key

question_choice_id

Foreign key → question_choices.id

answer_id

Foreign key → answers.id

deleted_at

Soft delete

company_id

Tenant key

created_at

Timestamp

updated_at

Timestamp