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.
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.
| Entity ID | Snapshot Date |
|---|---|
| E100 | 2026-08-03 |
| E101 | 2026-08-03 |
| E100 | 2026-08-10 |
| E101 | 2026-08-10 |
| E103 | 2026-08-10 |
| Entity ID | Update Date | Amount |
|---|---|---|
| E100 | 2026-07-15 | 300.00 |
| E101 | 2026-07-20 | 250.00 |
| E100 | 2026-08-05 | 350.00 |
| E101 | 2026-08-08 | 275.00 |
| E103 | 2026-08-09 | 500.00 |
La tabla secundaria representa historial individual por entidad. Cada Entity puede tener su propia última fecha válida.
Entity ID visible.Snapshot Date que se quiere reconstruir.Update Date <= Snapshot Date.SUMX(VALUES(...)).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
)
)
)
| Update Date | Entity ID | Amount |
|---|---|---|
| 2026-08-01 | E100 | 400.00 |
| 2026-08-01 | E101 | 400.00 |
| 2026-08-01 | E102 | 400.00 |
| 2026-08-08 | E100 | 400.00 |
| 2026-08-08 | E101 | 400.00 |
| 2026-08-08 | E103 | 400.00 |
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.
Snapshot Date maestra.Update Date <= Snapshot Date.TREATAS.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]
)
)
| Entity ID | Period | Current Result |
|---|---|---|
| E100 | 07/20/2026 - 08/02/2026 | 15.00 |
| E101 | 07/20/2026 - 08/02/2026 | 20.00 |
| E102 | 07/20/2026 - 08/02/2026 | 10.00 |
| E100 | 08/03/2026 - 08/16/2026 | 18.00 |
| E101 | 08/03/2026 - 08/16/2026 | 22.00 |
| E103 | 08/03/2026 - 08/16/2026 | 30.00 |
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.
Period Start Date.Period Start Date =
VAR _PeriodText =
LEFT ( 'PeriodicData'[Period], 10 )
RETURN
DATE (
VALUE ( RIGHT ( _PeriodText, 4 ) ),
VALUE ( LEFT ( _PeriodText, 2 ) ),
VALUE ( MID ( _PeriodText, 4, 2 ) )
)
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.
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.
La fórmula depende del significado temporal de la Source.
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.
Entity → As-Of Date → Last Valid Update → Value
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.
Fecha de análisis → último snapshot global → filtrar entidades → agregar
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.
Normaliza una sola vez las transformaciones determinísticas y reutilizables.
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.
SUMX( VALUES(Entity ID), evaluate business rule )
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.
Performance = Formula + Model + Visual + UX.
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.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.
Completa los 12 Practice Cases e ingresa tu nombre.