Desde que apareció el leguaje DAX se han ido creando multitud de expresiones de múltiples tipos y distintas complejidades, pero se ha apreciado que existen patrones que se utilizan muy a menudo. Uno de estos patrones es el de analizar a que nivel de granularidad nos encontramos para hacer un cálculo u otro, por ejemplo, imaginemos que tenemos que hacer el siguiente cálculo:
- Medida que a nivel día calcule la suma de ventas, a nivel de mes calcule la media de las ventas y a nivel de año calcule el máximo de las ventas, dejando el resto de niveles temporales en blanco.
Para crear este ejemplo utilizaremos el libro de Adventure Works que venimos utilizando en los post sobre PowerPivot, este sería el resultado del calculo:
Y este sería el cálculo que hemos aplicado:
=IF(COUNTROWS(VALUES(DimDate[FullDateAlternateKey]))=1, SUM(FactInternetSales[SalesAmount]), IF(COUNTROWS(VALUES(DimDate[EnglishMonthName]))=1, AVERAGE(FactInternetSales[SalesAmount]), IF(COUNTROWS(VALUES(DimDate[CalendarYear]))=1 && COUNTROWS(VALUES(DimDate[CalendarSemester]))>1 && COUNTROWS(VALUES(DimDate[CalendarQuarter]))>1, MAX(FactInternetSales[SalesAmount]), BLANK() ) ) )
Básicamente lo que hacemos con esta expresión es ir comprobando el contexto para determinar que cálculo debemos realizar, estas validaciones de contexto las hacemos contando con countrows los registros filtrados de una columna concreta, registros que obtenemos con la función values. De manera que la combinación de countrows y values de una columna nos informará de cuantos miembros de esa columna hemos filtrado en ese contexto.
Con la nueva versión de PowerPivot y HASONVALUE podemos acortar esta expresión haciendo la siguiente sustitución:
COUNTROWS(VALUES(<X>))=1 <----------------> HASONVALUE(<X>)
Quedando la expresión de la siguiente manera:
=IF(HASONEVALUE(DimDate[FullDateAlternateKey]), SUM(FactInternetSales[SalesAmount]), IF(HASONEVALUE(DimDate[EnglishMonthName]), AVERAGE(FactInternetSales[SalesAmount]), IF(HASONEVALUE(DimDate[CalendarYear]) && NOT(HASONEVALUE(DimDate[CalendarSemester])) && NOT(HASONEVALUE(DimDate[CalendarQuarter])), MAX(FactInternetSales[SalesAmount]), BLANK() ) ) )
Aquí podemos ver la comparación de los dos cálculos:
Cómo podemos ver, la expresión se hace mucho más comprensible y ocupa menos espacio, por lo que seremos más eficientes y claros al escribir nuestro código DAX. Podéis encontrar otro ejemplo de esta función y otras muy interesantes en el webcast sobre DAX del 24 de Noviembre.
Espero que os guste y nos vemos en futuros posts.
Ilde