El mundo de DAX esta que arde con el lanzamiento de las funciones nuevas a fines del año 2022. Muchos posts en distintos blogs han aparecido mostrando muchos escenarios explicando las funciones nuevas.
La mayoría de los artículos intenta explicar las funciones. Este artículo va a pasar eso por alto y va a intentar comparar como responden las funciones de time intelligence con el código tradicional respecto a las nuevas funciones de DAX para resolver esos clásicos escenarios de fecha.
Antes de dar inicio al artículo vamos a dejar un enlace a la documentación de Microsoft de las nuevas funciones DAX 2022. De ésta forma podes interiorizarte con OFFSET y WINDOW antes de iniciar.
https://learn.microsoft.com/es-es/dax/new-dax-functions
El análisis aplicado será realizado sobre un Adventure works en modo importado. Lo primero que vamos a hacer es aprender a construir algunos escenarios clásicos de Time Intelligence con las nuevas funciones. Veamos ejemplos para LY (Año Anterior), LM (Mes Anterior) y YTD (Año total meses acumulados).
Año Anterior (LY)
Normalmente para construir esta función podemos usar DATEADD o SAMEPERIODLASTYEAR. Veamos un ejemplo para una medida de [Net Price AC]
Net Price LY =CALCULATE(
[Net Price AC]
, SAMEPERIODLASTYEAR(TablaFecha[Fecha])
)
Ahora veamos la traducción a las nuevas medidas.
OFFSET
Net Price LY OFF =
CALCULATE(
[Net Price AC],
OFFSET(
-1,
ALL(TablaFecha[Año])
)
)
WINDOW
Net Price LY WIN =
CALCULATE(
[Net Price AC],
WINDOW(
-1,REL,-1,REL,
ALL(TablaFecha[Año])
)
)
De forma predeterminada cuando no especificamos valores de ORDERBY y PARTITIONBY, tomaría lo expresado en la tabla de relación. En este caso los valores distintivos de Año.
En un rápido chequeo podemos apreciar todo acorde:

Mes Anterior (LM)
En estos casos podemos usar tanto DATEADD como PREVIOUSMONTH, sigamos nuestro ejemplo con Net Price AC
Net Price LM =
CALCULATE(
[Net Price AC]
, PREVIOUSMONTH(TablaFecha[Fecha])
)
Ahora veamos la traducción a las nuevas medidas.
OFFSET
Net Price LM OFF =
CALCULATE(
[Net Price AC]
, OFFSET(
-1
, ALL(TablaFecha[Año], TablaFecha[IdMes], TablaFecha[Mes], TablaFecha[Periodo])
, ORDERBY(TablaFecha[Periodo])
)
)
WINDOW
Net Price LM WIN =
CALCULATE(
[Net Price AC],
WINDOW(
-1,REL,-1,REL,
ALL(TablaFecha[Año], TablaFecha[IdMes], TablaFecha[Mes], TablaFecha[Periodo]),
ORDERBY(TablaFecha[Periodo])
)
)
La traducción esta vez es un poco más compleja. Requerimos más que solo año para poder hacerle entender al motor lo querepresenta un mes. Podemos usar el par Mes y IdMes o podemos usar Periodo. Yo expresé ambos para tener la libertad de que la medida funcione para ambas columnas llegado el caso de una visualización. El IdMes es el número de mes que da orden al nombre de mes. Por esa última razón es necesario incluirlo en la tabla relativa que vamos a explorar.
Vistazo validando valores:

Año total meses acumulados (YTD)
Para este escenario vamos a usar la medida Quantity AC
Quantity YTD =
CALCULATE(
[Quantity AC]
, DATESYTD(TablaFecha[Fecha])
)
OFFSET. De momento no disponemos de una medida con esta función porque la función realiza un desplazamiento determinado para recuperar el valor de una fila y no para agregar o acumular un conjunto de filas. Puede que existan formas de ejecutar la acción pero seguramente requerirían acciones adicionales que hagan más compleja la resolución. Como estamos buscando la mejor forma para resolver esto, dudo que esta opción aplique.
Ahora veamos la traducción a la nueva medida
WINDOW
Quantity YTD WIN =
CALCULATE(
[Quantity AC],
WINDOW(
1,ABS,0,REL,
ALL(TablaFecha[Año], TablaFecha[IdMes], TablaFecha[Mes], TablaFecha[Periodo]),
ORDERBY(TablaFecha[Periodo]),
PARTITIONBY(TablaFecha[Año])
)
)
La clave en esta oportunidad es que el acumulado comience al primer índice absoluto y termine en el actual relativo particionado por año. De este modo acumula valores desde el inicio de la partición hasta el último.
Validamos la solución:

Ahora que todo se dispone de la mejor manera vamos a mediar la performance de nuestras medidas como sugiere SQLBI. Una página en blanco donde inicia nuestro PowerBi Desktop para tener todas las memorias cache limpias y recien prenderíamos el Performance Analyzer para ver los números de las visualizaciones en limpio.
LY

Dentro del tiempo de cada visualización para LY podemos apreciar que no hay mucha diferencia en cuanto a performance, si bien demoró menos OFFSET en la totalización el detalle nos indica que DAX Query demora exactamente lo mismo para cada medida.
LM

Para lo que es el Mes ya tenemos una diferencia que se presenta más que nada por el abarcar columnas de Mes, IdMes y Periodo. Cuando hice la prueba con simplemente periodo los tres números estaban más cerca y menores a 30 en DAX Query. Seguía ganando TI (TimeIntelligence) por poco.
YTD

Finalmente acumulando tampoco hemos encontrado grandes diferencias.
Conclusión
Las nuevas funciones tienen un gran poder para recorrer y traer valores de un contexto. Pueden buscar por indice o cantidad en un cierto orden. Son muy poderosas para escenarios de búsqueda bajo índices numéricos o de texto. Sin embargo, las nuevas funciones no son mejores ni funcionan mejor para escenarios tradicionales de fecha con un conjunto de datos importado. Las nuevas funciones NO reemplazarían a las de Time Intelligence tradicionales que venimos usando hace ya bastante tiempo.
Tengan cuidado en escenarios de Direct Query puesto que allí si se ha notado diferencia y Chris Webb lo demostró en un artículo de su blog.
Como siempre pueden encontrar el archivo de PowerBi Desktop de prueba en mi github. Espero que les haya sido útil el análisis.