Analyze Direct: Key Fields vs. ID Fields

The Analyze Direct data model includes two types of identifier fields: Surrogate Key fields (for relationships) and Guaranteed Unique ID fields (for persistent references). This article explains how to use each field type to keep joins, filters, saved reports, and change tracking reliable over time.

 

Key Fields and ID Fields in Analyze Direct

This section defines Surrogate Key fields and Guaranteed Unique ID fields, and explains when to use each.

 

Identifier Field Types

Analyze Direct uses the following identifier field types:

  • Surrogate Key fields (for example, COURSE_KEY).
  • Guaranteed Unique ID fields (for example, COURSE_ID).

 

What Is a Surrogate Key?

A Surrogate Key is a system-generated internal identifier used to maintain relationships between tables in the data warehouse.

 

Examples

The following are common Surrogate Key fields:

  • COURSE_KEY
  • USER_KEY
  • SESSION_KEY

 

Characteristics

Surrogate Keys are:

  • Numeric.
  • Optimized for joins and warehouse performance.
  • Used to relate fact and dimension tables.
  • Not guaranteed to remain constant over time.
  • May change during data rebuilds, migrations, or model updates.

 

Surrogate Keys are designed for internal relational mechanics and not long-term filtering.

 

What Is a Guaranteed Unique Identifier?

A Unique ID field represents the true, immutable business identifier of the object.

 

Examples

The following are common Unique ID fields:

  • COURSE_ID
  • USER_ID
  • SESSION_ID

 

Characteristics

Unique ID fields are:

  • Guaranteed unique.
  • Immutable for the life of the object.
  • Safe for saved filters, integrations, and persistent reporting.

 

If a report needs to consistently reference the same course over time, the filter must use COURSE_ID and not COURSE_KEY.

 

Key Takeaway

Use Surrogate Keys for joins and Unique IDs for filters and persistent references.

  • Surrogate Keys maintain relationships.
  • Unique IDs provide an immutable reference.

 

Surrogate Key values are subject to change. If a filter must remain correct over time, it must use the immutable *_ID field and not the *_KEY field.

 

Best Practices in SQL

Use Surrogate Keys to join related tables, and use Unique IDs when filtering for specific records.

 

Correct: Using Surrogate Keys in JOIN Statements

Surrogate Keys are appropriate when joining tables within your Snowflake warehouse.

In this example, COURSE_KEY maintains the table relationship and COURSE_ID is returned as the stable reference.

SELECT
  c.COURSE_ID,
  c.COURSE_NAME,
  e.USER_ID,
  e.COMPLETION_DATE
FROM FACT_ENROLLMENT e
JOIN DIM_COURSE c
  ON e.COURSE_KEY = c.COURSE_KEY;

 

Correct: Using Unique IDs in WHERE Clauses

When filtering for specific records, always use immutable ID fields.

This helps ensure filters continue to work correctly and reports remain accurate after warehouse updates.

SELECT
  USER_ID,
  COMPLETION_DATE
FROM FACT_ENROLLMENT
WHERE COURSE_ID = '964e6eee-56dd-4d4c-9f77-10b89a52a0fe';

 

Incorrect: Filtering with Surrogate Keys

Filtering with Surrogate Keys is risky because key values can be regenerated or remapped. This can cause saved reports to silently return incorrect results or filters to break without warning.

SELECT
  USER_ID,
  COMPLETION_DATE
FROM FACT_ENROLLMENT
WHERE COURSE_KEY = 12345;

 

Best Practice Pattern

Use the following pattern in your SQL and reporting tools:

  • JOIN using Surrogate Keys.
  • FILTER using immutable Unique Identifiers.

 

Example Combining Both

This example joins using COURSE_KEY and filters using COURSE_ID.

SELECT
  c.COURSE_ID,
  COUNT(*) AS Total_Completions
FROM FACT_ENROLLMENT e
JOIN DIM_COURSE c
  ON e.COURSE_KEY = c.COURSE_KEY
WHERE c.COURSE_ID IN (
  '964e6eee-56dd-4d4c-9f77-10b89a52a0fe',
  'b85a49c4-8368-4223-8596-a643d2145ed4'
)
GROUP BY c.COURSE_ID;

 

Field Use Case Summary

The following table summarizes when to use each field type.

Joining tablesSurrogate Key (*_KEY)
Filtering recordsUnique ID (*_ID)
Saved reportsUnique ID
Power BI slicersUnique ID
Persistent integration referencesUnique ID

 

Proper Use in Upserts 

An upsert operation updates an existing row, or inserts a new row if one does not exist. This requires a stable way to identify whether a record already exists. 

Analyze Direct provides a read-only version of your LMS data in your Snowflake warehouse.  Actions described in this section can be performed on copies of your LMS data, for example, COPY_OF_COURSE is a copy of DIM_COURSE.

Core Rule for Upserts

Always match rows using the Unique Identifier (*_ID), never the Surrogate Key (*_KEY).

 

Why Surrogate Keys Must Not Be Used in Upserts

Surrogate Keys are generated after insertion, may change across data loads, and do not represent real-world identity. Using them in upserts causes duplicate records, failed matches, and data corruption over time. 

 

Incorrect: Upsert Using a Surrogate Key

The following example shows an incorrect merge statement that uses COURSE_KEY (a Surrogate Key) as the match condition. The source system typically does not control COURSE_KEY, keys may not align between staging and target, and the result is duplicate or missed records.

MERGE INTO COPY_OF_COURSE target
USING STAGING_COURSE source
ON target.COURSE_KEY = source.COURSE_KEY  -- Incorrect: surrogate key
WHEN MATCHED THEN
    UPDATE SET target.COURSE_NAME = source.COURSE_NAME
WHEN NOT MATCHED THEN
    INSERT (COURSE_KEY, COURSE_NAME)
    VALUES (source.COURSE_KEY, source.COURSE_NAME);

 

Correct: Upsert Using a Unique Identifier

The following example shows a correct merge statement that uses COURSE_ID (a Unique Identifier) as the match condition. Since COURSE_ID is stable and meaningful, this approach ensures correct matching across loads and prevents record duplication.

MERGE INTO COPY_OF_COURSE target
USING STAGING_COURSE source
ON target.COURSE_ID = source.COURSE_ID  -- Correct: unique identifier
WHEN MATCHED THEN
    UPDATE SET
        target.COURSE_NAME = source.COURSE_NAME,
        target.LAST_UPDATED_DATE = CURRENT_TIMESTAMP
WHEN NOT MATCHED THEN
    INSERT (COURSE_ID, COURSE_NAME, CREATED_DATE)
    VALUES (source.COURSE_ID, source.COURSE_NAME, CURRENT_TIMESTAMP);

 

Common Upsert Errors

The following table describes common errors made when writing upsert statements and the impact of each.

ErrorResult
Matching on *_KEYDuplicate records or missed updates
Using changing fields (for example, name) to matchIncorrect merges
Not enforcing uniqueness on *_IDData drift over time
Re-generating Surrogate Keys for existing recordsBroken table relationships

 

Key Takeaway

Surrogate Keys maintain relationships between tables. Unique IDs define the identity of a record. Any process that depends on stability over time, such as filters, reports, integrations, or upserts, must use the immutable *_ID field, never the *_KEY.

 

List of Analyze Direct Key Fields and Corresponding Unique ID Fields

The following table maps Surrogate Key fields to their guaranteed Unique Identifier equivalents.

Table NameSurrogate KeyUnique Identifier Fields
DIM_ASSESSMENT_QUESTIONQUESTION_KEYQUESTION_ID
DIM_ASSESSMENT_QUESTION_OPTIONQUESTION_OPTION_KEYQUESTION_OPTION_ID
DIM_CATEGORYCATEGORY_KEYCATEGORY_ID
DIM_CHAPTERCHAPTER_KEYCHAPTER_ID
DIM_CLASSCLASS_KEYCLASS_ID
DIM_COMPETENCY_CATEGORYCOMPETENCY_CATEGORY_KEYCOMPETENCY_CATEGORY_ID
DIM_COMPETENCY_DEFINITIONCOMPETENCY_DEFINITION_KEYCOMPETENCY_DEFINITION_ID
DIM_COUPONCOUPON_KEYCOUPON_ID
DIM_COURSECOURSE_KEYCOURSE_ID
DIM_COURSE_BUNDLECOURSE_BUNDLE_KEYCOURSE_BUNDLE_ID
DIM_COURSE_SKILLSKILL_KEYSKILL_ID
DIM_COURSE_UPLOAD_DEFINITIONCOURSE_UPLOAD_DEFINITION_KEYCOURSE_UPLOAD_DEFINITION_ID
DIM_CURRICULUMCURRICULUM_KEYCURRICULUM_ID
DIM_CURRICULUM_GROUPCURRICULUM_GROUP_KEYCURRICULUM_GROUP_ID
DIM_DEPARTMENTDEPARTMENT_KEYDEPARTMENT_ID
DIM_DIRECT_INDIRECT_MANAGERMANAGER_KEYMANAGER_ID
DIM_ENROLLMENT_KEYENROLLMENT_KEY_KEYENROLLMENT_KEY_ID
DIM_EVALUATION_QUESTIONQUESTION_KEYQUESTION_ID
DIM_EXTENSION_PRICEEXTENSION_PRICE_KEYEXTENSION_PRICE_ID
DIM_EXTERNAL_TRAINING_TEMPLATEEXTERNAL_TRAINING_TEMPLATE_KEYEXTERNAL_TRAINING_TEMPLATE_ID
DIM_GROUPGROUP_KEYGROUP_ID
DIM_JOB_ROLEJOB_ROLE_KEYJOB_ROLE_ID
DIM_LESSONLESSON_KEYLESSON_ID
DIM_PRICEPRICE_KEYPRICE_ID
DIM_ROLEROLE_KEYROLE_ID
DIM_SESSIONSESSION_KEYSESSION_ID
DIM_TAGTAG_KEYTAG_ID
DIM_USERUSER_KEYUSER_ID
DIM_VENUEVENUE_KEYVENUE_ID
FACT_ATTEMPTATTEMPT_KEYATTEMPT_ID
FACT_ATTEMPT_SUMMARYLESSON_ENROLLMENT_KEYLESSON_ENROLLMENT_ID
FACT_ATTENDANCEATTENDANCE_KEYATTENDANCE_ID
FACT_AWARDED_CERTIFICATEAWARDED_CERTIFICATE_KEYCERTIFICATE_ID
FACT_CHECKLIST_REVIEWCHECKLIST_REVIEW_KEYREVIEW_ID
FACT_CHECKLIST_REVIEW_STEPCHECKLIST_REVIEW_STEP_KEYREVIEW_STEP_ID
FACT_COURSE_BUNDLE_ENROLLMENTCOURSE_BUNDLE_ENROLLMENT_KEYCOURSE_BUNDLE_ENROLLMENT_ID
FACT_COURSE_ENROLLMENTCOURSE_ENROLLMENT_KEYCOURSE_ENROLLMENT_ID
FACT_CURRICULUM_ENROLLMENTCURRICULUM_ENROLLMENT_KEYCURRICULUM_ENROLLMENT_ID
FACT_EXTERNAL_TRAINING_SUBMISSIONEXTERNAL_TRAINING_SUBMISSION_KEYSUBMISSION_ID
FACT_LESSON_ENROLLMENTLESSON_ENROLLMENT_KEYLESSON_ENROLLMENT_ID
FACT_LOGIN_SUMMARYUSER_KEYUSER_ID
FACT_QUESTION_ANSWERASSESSMENT_ANSWER_KEYASSESSMENT_ANSWER_ID
FACT_QUESTION_RESULTASSESSMENT_ACTIVITY_KEYASSESSMENT_ACTIVITY_ID
FACT_SELF_ASSESSMENTSELF_ASSESSMENT_KEYSELF_ASSESSMENT_ID
FACT_SESSION_ENROLLMENTSESSION_ENROLLMENT_KEYSESSION_ENROLLMENT_ID
FACT_SHOPPING_CART_TRANSACTIONSHOPPING_CART_TRANSACTION_KEYSHOPPING_CART_TRANSACTION_ID
Was this article helpful?
0 out of 0 found this helpful

Comments

0 comments

Article is closed for comments.