Person ≠ Employee — and How to Join Them Correctly

Overview

One of the most common points of confusion in the CDM is the relationship between Person and Employee.

At first glance, they appear similar. In practice, they serve different purposes, operate at different levels of detail, and must not be joined using the same keys.

Getting this wrong leads to:

  • duplicate records
  • broken relationships in Power BI
  • incorrect headcount and reporting

This article explains the difference and shows the correct way to work with both domains.


The Core Principle

Person represents identity. Employee represents employment.

These are not interchangeable.


Person Domain (Who someone is)

The Person domain provides a canonical, company-neutral identity.

Key Characteristics

  • One row represents one individual
  • Not tied to a specific company or contract
  • Designed for identity resolution across systems

Key Structure

OBJECT_SEQ = { COMPANY_ID: "9900", PERSON_UID: "<unique_id>" }
  • PERSON_UID = the canonical identity key
  • COMPANY_ID = 9900 = neutral (not tied to a legal entity)

Employee Domain (How someone is employed)

The Employee domain represents employment instances.

Key Characteristics

  • One person can have multiple employee records
  • Each record is tied to:
    • a company
    • a contract
    • a period of employment

Key Structure

OBJECT_SEQ = { COMPANY_ID: "<entity>", EMP_NO: "<employee_number>" }
  • EMP_NO = employment instance identifier
  • COMPANY_ID = legal entity

Why OBJECT_SEQ Does Not Match

This is intentional design, not an issue.

DomainRepresentsKey Type
PersonIdentityPERSON_UID
EmployeeEmploymentEMP_NO

Attempting to align these would:

  • remove the distinction between identity and employment
  • introduce ambiguity
  • break historical and multi-employment scenarios

👉 Do not attempt to join Person ↔ Employee using OBJECT_SEQ


The Correct Way to Join

Use PERSON_UID as the bridge

The Employee domain exposes identity via KEY_CODE attributes.

Example Join Logic

Person.PERSON_UID = Employee.PERSON_UID

This allows:

  • one Person → many Employees (correct)
  • consistent identity tracking across roles and companies

Common Pitfalls (Avoid These)

❌ Joining on OBJECT_SEQ

This will:

  • fail
  • or worse, partially work and produce incorrect results

❌ Assuming 1:1 relationship

A person may:

  • move companies
  • hold multiple roles
  • be rehired

👉 Always expect 1-to-many


❌ Treating Employee as identity

Employee is context, not identity.


Understanding Duplicates

If you see multiple rows for the same name, it is usually one of:

1. Multiple employment records (Expected)

✔ Same PERSON_UID
✔ Different EMP_NO


2. Multiple identities (Needs review)

❗ Different PERSON_UID

Caused by:

  • missing or inconsistent source identifiers
  • multiple accounts (e.g. global vs local)
  • lack of a shared key (email, Entra ID, payroll)

Current Limitations (Preview Phase)

The CDM is evolving. At present:

  • Not all attributes are time-bound
  • Some identity links depend on source system quality
  • Attribute-level history is not fully implemented

This means:

  • “current” values are reliable
  • full historical tracking is still developing

Recommended Modelling Approach (Power BI)

When building reports:

  1. Use Person for:
    • headcount
    • identity-level reporting
  2. Use Employee for:
    • employment attributes (role, org, payroll)
    • company-specific analysis
  3. Join using:
PERSON_UID
  1. Always validate:
  • relationship cardinality (1 → many)
  • duplication impact on measures

Future Direction

To further strengthen this model, the following enhancements are planned:

  • Attribute-level time-bound history
  • A formal person ↔ employee bridge
  • Improved identity resolution rules

Summary

  • Person and Employee are different by design
  • OBJECT_SEQ is not a cross-domain key
  • PERSON_UID is the correct linking mechanism
  • Multiple employee records per person are expected

If in doubt:
Join on identity, not structure.


Leave a Comment