[DAX] SUM vs SUMX

Cuando comenzamos con Power Bi una de las cosas más atractivas que nos atrapa es el código DAX. Sentimos un entorno familiar con sintaxis semejante a excel, pero no por eso vamos a decir que el lenguaje es parecido, que nos permite construir cálculos y medidas matemáticas que resuelven nuestras lógicas de negocio.

Ciertamente nos da fuerza sentirlo conocido para comenzar de golpe con todas las reglas sin importar la dificultad llegando así a una traba. El freno o bloqueo inicial son las funciones de agregación "X". Cuando vamos a constuir nuestra medida nos encontramos no solo con COUNT, AVERAGE, MAX o SUM sino también con COUNTX, AVERAGEX, MAXX, SUMX y nos deja pensando sin conocer bien como deberíamos utilizar dichas funciones.
En este artículo vamos a ver como responden dichas funciones enfocandonos en SUM y SUMX para conocer el concepto que las diferencia. Esto no solo serviría para SUM sino también para las otras agregaciones pero para facilitar la descripción e interpretación usaremos una de ellas como guía.

Descripción Teórica

Según dax.guide:

  • SUM: Suma todos los valores de una columna
image
  • SUMX: devuelve la suma de una expresión de una tabla evaluada fila a fila.
image

Comparación

La mayor diferencia entre ellas es que las funciones X nos permitirían realizar una operación determinada barrida fila a fila antes de agregar los valores. Esto quiere decir que va a iterar la <table> definida por parámetro.

Ejemplo:

En la siguiente imagen tenemos un SUM y un SUMX. La función SUM solo nos permite agregar una columna. En este caso será Unit Cost. Por otro lado tendremos un SUMX que multiplica el Unit Cost por Quantity para saber cuanto es el costo real que tuvimos ese día.

image

SUM sumará uno por uno los valores de la columna:

878,96 + 404,88 + 60,78 + 23,45…

A diferencia de SUMX que multiplicaría los valores antes de sumar 

(4 * 878,96) + (4 * 404,88) + (4 * 60,78) + (4 * 23,45)…

Las agregaciones X nos permite ejecutar una operación <expression> para cada fila dentro de nuestra <table> en el parámetro. Muchas veces puede suceder que necesitamos en nuestra matemática que antes de agregar para un promedio, un máximo, etc. es necesario hacerlo sobre un cálculo previo. No sería lo mismo calcula el máximo UnitPrice que la máxima venta del día (UnitPrice * Quantity). 

Para que se den una idea en lo que significa iterar o ir fila a fila. Usar SUMX de una tabla sería como construir una nueva columna en DAX de la siguiente manera: 

NuevaColumna = InternetSales[UnitCost] * InternetSales[Quantity]

Para luego llamar a dicha columna dentro de una función SUM. Nuestra nueva columna ejecutaría la fórmula en cada fila de nuestra tabla.

image

Luego le podemos aplicar un SUM. El resultado de la ejecución será el mismo que ejecutar un SUMX de dicha multiplicación como vimos anteriormente. 

Si bien ahora podrán preguntarse ¿Para que usar SUMX cuando puedo crear columnas? lo cierto es que no siempre necesitaremos iterar una tabla completa de las que tenemos cargadas en el modelo. Puede ocurrir que necesitemos recorrer una tabla virtual o relatedtable del modelo la cual no existe la posibilidad de agregarle una columna como tal.

Encrucijada 

La mayor dificultad para una medida no estará solamente entre sum y sumx, sino más bien entre CALCULATE( SUM() ) y SUMX(). La función calculate no voy a describirla en este post porque tiene muchísimo para hablar sobre ella misma. Lo importante es diferenciar las ejecuciones en este caso para conocer cual utilizar.

Como sabemos, SUM nos devolvería un valor que resulta de la suma de una columna. Esto no siempre será útil para nuestros calculos dado que la mayoría de las veces no tenemos que hacerlo para toda la columna de la tabla sino que debemos ejecutarlo bajo ciertas condiciones como los valores de la tabla "InternetSales" cuando su tuvo un descuento aplicado "Unit Discount". En dicho caso lo primero que pensaríamos es que tenemos que preguntar en cada fila si tiene un descuento aplicado antes de sumar. Por lo tanto debemos usar SUMX. Resulta que CALCULATE los ayudará a poder resolver una agregación simple como COUNT para una tabla transformada/filtrada previamente. Por ejemplo si queremos conocer la cantidad de ventas con descuento podríamos contar las fechas de las ventas de la siguiente manera:

image

Con calculate podemos aplicar una transformación antes de ejecutar la agregación. Podemos usar FILTER o filtrar bajo una condición que va a ejecutarse antes de nuestro COUNT. De esa forma obtendríamos el mismo valor que si vamos preguntando fila a fila con COUNTX si tiene descuento mayor a cero la fila antes de incluirla en el conteo.

¿Cuando usaremos cada una? la realidad vuelva a ser la misma que antes. Utilizaremos las funciones agregadas X cuando necesitemos una matemática calculada fila por fila. Si es un filtro como mayor, menor, igual etc lo que necesitamos para cada fila, podemos usar calculate para ahorrar el recorrido. Ambos ejemplos no siempre devolverán el mismo resultado y esto puede deberse a que una de las opciones no está ejecutando fila por fila. Pensemos bien si lo que necesitamos es un simple filtro por cada fila o si lo que necesitamos es una matemática por cada fila antes de ser agregada.

Hemos llegado al final del artículo y espero que hayan comprendido la diferencia de las funciones. Si bien no definimos a calculate es importante que lo comprendan contra los casos más típicos que van a ocurrir puesto que la diferencia entre usar sum y sumx está más que clara. El verdadero desafío se presenta entre calculate de sum y sumx.