Cómo comparar periodos en DAX: YoY, YTD, MAT y periodos anteriores
En el análisis de datos empresarial, la capacidad de comparar el rendimiento actual con periodos pasados no es una funcionalidad opcional; es la base de la toma de decisiones. Sin embargo, en mis años como consultor de Business Intelligence, he observado que las funciones de Time Intelligence en DAX son las que más errores conceptuales y de rendimiento generan en los informes de Power BI. No se trata solo de arrastrar una medida, sino de entender cómo el motor de DAX manipula el contexto de filtro para devolver un resultado coherente.
El problema habitual no es que la fórmula falle, sino que devuelva un número que parece correcto pero es semánticamente erróneo. Por ejemplo, comparar un mes de marzo incompleto contra un marzo completo del año anterior sin ajustar la proporcionalidad, o mostrar crecimientos del 100% en fechas donde no existen datos previos. Estos fallos minan la confianza del usuario final en el dashboard.
En este artículo, vamos a desglosar los patrones correctos para implementar YoY (Year-over-Year), YTD (Year-to-Date) y MAT (Moving Annual Total), centrándonos en la robustez del código y en evitar los cuellos de botella que suelen aparecer en modelos de gran volumen.
El requisito innegociable: La tabla de Calendario
Antes de escribir una sola línea de DAX para comparar periodos, debemos asegurar la infraestructura. Las funciones de inteligencia de tiempo de Microsoft requieren, por diseño, una tabla de dimensiones de fecha (Calendario) que cumpla con requisitos estrictos: fechas contiguas (sin saltos), que cubran años completos y que la columna de fecha sea de tipo Date o DateTime. Si intentas usar estas funciones directamente sobre la columna de fecha de tu tabla de Ventas, el motor de DAX creará tablas de fechas ocultas por debajo, lo cual es una de las prácticas que más perjudican el rendimiento y el tamaño del modelo.
En mis proyectos, siempre recomiendo marcar la tabla como "Tabla de fechas oficial" en Power BI. Esto desactiva las jerarquías automáticas y obliga al motor a usar nuestra dimensión optimizada. Si tienes dudas sobre cómo estructurar estas métricas, es fundamental entender primero la diferencia entre columnas calculadas y medidas en DAX, ya que las comparativas temporales deben ser siempre medidas dinámicas para responder a los filtros del usuario.
YoY: DATEADD frente a SAMEPERIODLASTYEAR
Para calcular la variación respecto al año anterior (Year-over-Year), existen dos caminos principales. SAMEPERIODLASTYEAR es una función azúcar sintáctica, más fácil de leer pero menos flexible. Por otro lado, DATEADD es la navaja suiza del consultor de BI.
El error típico al usar estas funciones es no controlar el contexto de filtro. Cuando calculamos un porcentaje de crecimiento, es vital usar variables para mejorar la legibilidad y el rendimiento, evitando recalcular la misma expresión varias veces. El uso de Variables DAX (VAR) permite que el motor evalúe la métrica una sola vez y reutilice el resultado en la división final.
Ventas YoY % =
VAR _VentasActuales = [Total Ventas]
VAR _VentasAñoAnterior =
CALCULATE(
[Total Ventas],
DATEADD('Calendario'[Fecha], -1, YEAR)
)
VAR _Resultado =
IF(
ISBLANK(_VentasActuales) || ISBLANK(_VentasAñoAnterior),
BLANK(),
DIVIDE(_VentasActuales - _VentasAñoAnterior, _VentasAñoAnterior)
)
RETURN
_Resultado¿Por qué usamos DATEADD con -1 YEAR en lugar de SAMEPERIODLASTYEAR? Porque DATEADD nos permite parametrizar el desplazamiento. Si el cliente pide comparar contra el trimestre anterior o hace dos años, solo cambiamos los argumentos. Además, fíjate en el manejo de los blancos: si no hay ventas en el periodo actual o no las hubo en el anterior, devolvemos un BLANK. Esto evita que el gráfico muestre un crecimiento del -100% o +100% artificialmente en periodos donde la empresa aún no operaba.
YTD y el peligro de los periodos incompletos
El cálculo del acumulado anual (Year-to-Date) es sencillo con DATESYTD, pero esconde una trampa de visualización. Si hoy es 15 de mayo y comparamos el YTD de este año contra el YTD del año pasado, Power BI comparará los datos hasta el 15 de mayo de este año frente al año pasado COMPLETO si no aplicamos un filtro de seguridad.
Para solucionar esto, debemos limitar el cálculo del año anterior hasta la misma fecha máxima que tenemos en el periodo actual. Es lo que llamamos "anclaje de fechas". Sin este ajuste, el análisis de tendencias es injusto y erróneo.
Al realizar estas operaciones, es común encontrarse con problemas de filtrado. Si necesitas que el acumulado ignore ciertos filtros externos pero mantenga la lógica temporal, te recomiendo revisar cómo funciona KEEPFILTERS en CALCULATE para no sobrescribir contextos de forma accidental.
MAT (Moving Annual Total): La métrica real de tendencia
Mientras que el YTD se reinicia cada 1 de enero, el Moving Annual Total (MAT) siempre suma los últimos 12 meses desde la fecha seleccionada. En sectores con alta estacionalidad, como el retail o la energía, el MAT es la métrica más valiosa porque suaviza los picos estacionales y muestra la dirección real del negocio.
Ventas MAT =
VAR _UltimaFecha = MAX('Calendario'[Fecha])
RETURN
CALCULATE(
[Total Ventas],
DATESINPERIOD(
'Calendario'[Fecha],
_UltimaFecha,
-1,
YEAR
)
)Este patrón utiliza DATESINPERIOD, que es extremadamente eficiente. Toma la última fecha visible en el contexto (por ejemplo, el último día del mes en una tabla por meses) y retrocede exactamente un año. Al comparar el MAT de este mes contra el MAT del mismo mes del año anterior, estamos comparando dos bloques de 12 meses, lo que elimina cualquier ruido por campañas puntuales de Navidad o verano.
Comparativa de funciones de Time Intelligence
No todas las funciones de tiempo se comportan igual ante el motor de almacenamiento (Storage Engine). Aquí una comparativa técnica para decidir cuál usar en cada escenario:
| Función | Uso Principal | Flexibilidad | Impacto en Rendimiento |
|---|---|---|---|
| SAMEPERIODLASTYEAR | YoY estándar | Baja (solo año anterior) | Óptimo |
| DATEADD | Cualquier desplazamiento | Muy Alta (días, meses, años) | Excelente |
| DATESYTD | Acumulados anuales | Media | Bueno |
| PARALLELPERIOD | Comparar niveles superiores | Media (salta al nivel completo) | Variable |
| DATESINPERIOD | MAT y medias móviles | Alta | Excelente |
Uno de los errores que más afectan al rendimiento, especialmente en modelos DirectQuery, es el uso de estas funciones sobre columnas que no están indexadas o que requieren transformaciones pesadas. Para entender mejor cómo el código DAX puede degradar la experiencia de usuario, consulta las 50 medidas y patrones DAX que destruyen el rendimiento.
El problema del "Ghosting" y divisiones por cero
Al calcular ratios de crecimiento, el uso de la barra inclinada (/) para dividir es una práctica de alto riesgo. Si el año anterior tuvo ventas cero, el informe mostrará un error de infinito o un valor no definido que romperá tus visuales. Siempre, sin excepción, utiliza la función DIVIDE. Esta función realiza internamente la comprobación de denominador cero y devuelve un BLANK (o el valor que definas) de forma segura.
Puedes profundizar en las razones técnicas de esta decisión en nuestro artículo sobre DIVIDE frente a la barra ‘/’ en DAX.
Checklist para implementar comparativas temporales
- ¿Tienes una tabla de Calendario marcada como tal y sin huecos en las fechas?
- ¿Has usado
DIVIDEpara todos los cálculos de variaciones porcentuales? - ¿Estás controlando los periodos incompletos para no comparar un mes parcial con uno entero?
- ¿Has encapsulado tus cálculos en variables para mejorar el rendimiento y evitar la redundancia?
- ¿Has verificado que no existan filtros cruzados que anulen la lógica de inteligencia de tiempo?
Preguntas frecuentes
¿Por qué mi medida de YoY devuelve el mismo valor que la medida actual?
Suele ocurrir porque no tienes una tabla de Calendario propiamente vinculada o estás usando una columna de fecha de la tabla de hechos. Sin una dimensión de fecha contigua, DAX no puede calcular el desplazamiento temporal y el contexto de filtro no cambia, devolviendo el valor del periodo actual.
¿Es mejor usar DATEADD o PARALLELPERIOD?
Depende del objetivo. DATEADD devuelve un conjunto de fechas desplazadas exactamente el intervalo indicado. PARALLELPERIOD siempre devuelve el periodo completo (mes, trimestre o año completo), independientemente de la selección de días. Para cálculos de YoY precisos a nivel de día, usa siempre DATEADD.
¿Cómo evito que el gráfico muestre el año que viene si aún no hay datos?
Debes añadir una condición en tu medida que verifique si hay datos en la tabla de hechos: IF( NOT ISBLANK([Total Ventas]), [MedidaTimeIntelligence] ). Esto forzará a Power BI a no renderizar puntos en el eje de tiempo para los cuales no existe actividad real.
¿Cuál es el coste de rendimiento de DATESYTD en modelos grandes?
En modelos en estrella bien diseñados, el coste es mínimo. Sin embargo, si la tabla de hechos tiene millones de filas y no está bien particionada, o si la tabla de calendario es excesivamente grande, el motor de DAX puede sufrir al generar el rango de fechas acumulado. Siempre mide con el Performance Analyzer.
antes de desplegar en producción.
»




