Article-Training Interactivo • Data Modeling & DAX
Case-Type Training • Analítica Histórica

ANALÍTICA HISTÓRICA AS‑OF

Reconstruyendo qué se sabía en cualquier punto del tiempo

Un Case Type reutilizable para analítica histórica cuando las tablas se actualizan en calendarios distintos. Aprende a distinguir Entity History de Complete Snapshots, normalizar Effective Dates, construir totales correctos y optimizar Performance.

Data → Descripción → Cómo Proceder → DAX → Practice Questions
CASE TYPEHistorical As-Of Analytics
MÓDULOS6
PRACTICE CASES12
TIEMPO35–50 min
Límite del training: Todos los nombres de tablas, entidades y amounts son genéricos. No se hace referencia a ninguna organización real, employee record, compensation field ni production schema.

Información del participante

Progreso del Training0 / 12
0%
Guided Case Walkthrough

Data → Descripción → Cómo Proceder → DAX → Practice Questions

Antes de responder las preguntas, estudia primero la estructura de la data, identifica el tipo de comportamiento temporal y sigue el procedimiento correspondiente. Los ejemplos son totalmente genéricos.

Case 1 — Last Known Value por Entity

1. Data

Entity IDSnapshot Date
E1002026-08-03
E1012026-08-03
E1002026-08-10
E1012026-08-10
E1032026-08-10
Entity IDUpdate DateAmount
E1002026-07-15300.00
E1012026-07-20250.00
E1002026-08-05350.00
E1012026-08-08275.00
E1032026-08-09500.00

2. Descripción

La tabla secundaria representa historial individual por entidad. Cada Entity puede tener su propia última fecha válida.

3. Cómo proceder

  1. Tomar el Entity ID visible.
  2. Tomar la Snapshot Date que se quiere reconstruir.
  3. Filtrar la tabla histórica por el mismo Entity ID.
  4. Mantener solamente registros con Update Date <= Snapshot Date.
  5. Seleccionar la fecha máxima válida.
  6. Recuperar el Amount asociado a esa fecha.
  7. Si hay múltiples entidades en contexto, evaluar la regla por entidad con SUMX(VALUES(...)).

4. DAX

Historical Value =
SUMX (
    VALUES ( 'MasterSnapshot'[Entity ID] ),

    VAR _EntityID =
        'MasterSnapshot'[Entity ID]

    VAR _AsOfDate =
        CALCULATE (
            MAX ( 'MasterSnapshot'[Snapshot Date] )
        )

    VAR _LastValidDate =
        CALCULATE (
            MAX ( 'EntityHistory'[Update Date] ),
            FILTER (
                ALL (
                    'EntityHistory'[Entity ID],
                    'EntityHistory'[Update Date]
                ),
                'EntityHistory'[Entity ID] = _EntityID
                    &&
                'EntityHistory'[Update Date] <= _AsOfDate
            )
        )

    RETURN
        CALCULATE (
            MAX ( 'EntityHistory'[Amount] ),
            FILTER (
                ALL (
                    'EntityHistory'[Entity ID],
                    'EntityHistory'[Update Date]
                ),
                'EntityHistory'[Entity ID] = _EntityID
                    &&
                'EntityHistory'[Update Date] = _LastValidDate
            )
        )
)

Case 2 — Last Global Snapshot

1. Data

Update DateEntity IDAmount
2026-08-01E100400.00
2026-08-01E101400.00
2026-08-01E102400.00
2026-08-08E100400.00
2026-08-08E101400.00
2026-08-08E103400.00

2. Descripción

Cada fecha representa un snapshot completo de la fuente. La pertenencia de una entidad al snapshot es parte de la data. Por eso no debemos buscar la última fecha de cada Entity de manera independiente.

3. Cómo proceder

  1. Tomar la Snapshot Date maestra.
  2. Buscar la última fecha global de la fuente secundaria con Update Date <= Snapshot Date.
  3. Usar exclusivamente las filas de ese snapshot.
  4. Transferir el conjunto de entidades visibles usando TREATAS.
  5. Agregar el Amount dentro de ese snapshot.

4. DAX

Snapshot Amount =
VAR _AsOfDate =
    MAX ( 'MasterSnapshot'[Snapshot Date] )

VAR _LastGlobalSnapshot =
    CALCULATE (
        MAX ( 'PeriodicSnapshot'[Update Date] ),
        REMOVEFILTERS ( 'PeriodicSnapshot'[Update Date] ),
        'PeriodicSnapshot'[Update Date] <= _AsOfDate
    )

VAR _VisibleEntities =
    VALUES ( 'MasterSnapshot'[Entity ID] )

RETURN
CALCULATE (
    SUM ( 'PeriodicSnapshot'[Amount] ),
    REMOVEFILTERS ( 'PeriodicSnapshot'[Update Date] ),
    'PeriodicSnapshot'[Update Date] = _LastGlobalSnapshot,
    TREATAS (
        _VisibleEntities,
        'PeriodicSnapshot'[Entity ID]
    )
)

Case 3 — Period Date Normalization

1. Data

Entity IDPeriodCurrent Result
E10007/20/2026 - 08/02/202615.00
E10107/20/2026 - 08/02/202620.00
E10207/20/2026 - 08/02/202610.00
E10008/03/2026 - 08/16/202618.00
E10108/03/2026 - 08/16/202622.00
E10308/03/2026 - 08/16/202630.00

2. Descripción

La fecha efectiva está almacenada dentro de un campo de texto. Si la extraemos dentro del measure en cada evaluación, Power BI repite operaciones de texto continuamente.

3. Cómo proceder

  1. Extraer los primeros 10 caracteres del Period.
  2. Convertir mes, día y año a una fecha real.
  3. Guardar el resultado en una columna reutilizable llamada Period Start Date.
  4. Usar esa nueva fecha en los measures históricos.

4. DAX

Period Start Date =
VAR _PeriodText =
    LEFT ( 'PeriodicData'[Period], 10 )

RETURN
DATE (
    VALUE ( RIGHT ( _PeriodText, 4 ) ),
    VALUE ( LEFT ( _PeriodText, 2 ) ),
    VALUE ( MID ( _PeriodText, 4, 2 ) )
)
Regla de decisión

Primero entiende qué representa la data. Después selecciona el temporal pattern. Luego escribe el DAX. Las Practice Questions aparecen después para comprobar si el patrón quedó entendido.

Módulo 1

Temporal Semantics antes de DAX

Un Master Snapshot puede describir una Entity en fechas específicas mientras otra tabla se actualiza solo periódicamente. Antes de escribir DAX, determina qué significa realmente cada Date: Event Date, Effective Date, Update Timestamp, Period Boundary o Complete Snapshot Date.

Applied lens

La fórmula depende del significado temporal de la Source.

Practice Case 1
¿Qué debe aclararse primero antes de escribir el measure?
Practice Case 2
¿Qué condición define una búsqueda histórica “as-of”?
Módulo 2

Pattern A — Last Known Value por Entity

Usa este Pattern cuando la tabla secundaria funciona como Entity-Level History. Para cada Entity y Analysis Date, busca registros donde Update Date sea menor o igual a la Analysis Date y luego selecciona la máxima fecha válida.

Pattern

Entity → As-Of Date → Last Valid Update → Value

Practice Case 3
¿Cuándo debe usarse este patrón?
Practice Case 4
¿Qué hace MAX(Update Date) después de aplicar el filtro histórico?
Módulo 3

Pattern B — Last Global Snapshot

Si cada Refresh es un Complete Snapshot, buscar por separado la última fecha de cada Entity puede revivir Entities que desaparecieron después. En su lugar, selecciona primero el Last Global Snapshot Date y utiliza únicamente ese Snapshot.

Pattern

Fecha de análisis → último snapshot global → filtrar entidades → agregar

Practice Case 5
¿Por qué la lógica de última fecha por entidad puede ser incorrecta para un snapshot completo?
Practice Case 6
¿Cuál es la secuencia correcta para una fuente de snapshots completos?
Módulo 4

Pattern C — Normalizar Period Dates

Si una Temporal Key está incrustada en texto como “08/02/2026 - 08/15/2026”, no la parsees repetidamente dentro de un Measure. Crea una Period Start Date reutilizable una sola vez, preferiblemente upstream.

Performance principle

Normaliza una sola vez las transformaciones determinísticas y reutilizables.

Practice Case 7
¿Por qué crear una columna Period Start Date?
Practice Case 8
¿Dónde deberían ocurrir idealmente las transformaciones determinísticas y reutilizables?
Módulo 5

Totals, SELECTEDVALUE y SUMX

Un Measure puede funcionar con una sola Entity seleccionada y fallar en Totals porque SELECTEDVALUE puede devolver BLANK cuando existen múltiples valores. Si la Business Rule debe evaluarse por Entity y luego sumarse, itera sobre VALUES(Entity ID) con SUMX.

Pattern

SUMX( VALUES(Entity ID), evaluate business rule )

Practice Case 9
¿Por qué SELECTEDVALUE puede romper un total?
Practice Case 10
¿Qué proporciona SUMX(VALUES(Entity ID), ...)?
Módulo 6

Performance y UX como parte del Model

Un DAX correcto todavía puede ser costoso. Los Historical Visuals pueden evaluar muchas Dates sobre muchas Entities. Prefiere Set-Based Filters, Precomputed Keys, menor Visual Concurrency y una UX deliberada. Una página de History puede cargar por default una sola Entity si eso coincide con la tarea real del usuario.

Design principle

Performance = Formula + Model + Visual + UX.

Practice Case 11
¿Qué cambio puede reducir el costo de los visuales históricos?
Practice Case 12
¿Cuál es la lección final de diseño más importante?
Master Decision Tree

Selecciona el Pattern antes de escribir el Measure

1. Entity-level history?
   → Last Known Value Per Entity

2. Complete refresh snapshot?
   → Last Global Snapshot

3. Effective date embedded in text?
   → Normalize the date upstream

4. Works for one entity but total is blank/wrong?
   → SUMX(VALUES(Entity ID), ...)

5. Correct but slow?
   → Optimize columns, use set-based logic, precompute stable transformations,
     and reduce expensive historical scope through UX when appropriate.

Knowledge Sample — Alcance

Este training es intencionalmente genérico y reutilizable. Adapta Relationships, Date Types, Aggregation Rules y Table Names al Model real antes de usarlo en Production.

Certificate of Participation

Completa los 12 Practice Cases e ingresa tu nombre.

0 / 12