Y por fin, con este post, llegamos a la última de las cuatro funciones tipo tabla más utilizadas en DAX, y no por ser la última es la menos importante. Esta función es CALCULATETABLE.
Lo primero, como es costumbre, vamos a ver la definición y sintaxis de Microsoft sobre la función y posteriormente la analizaremos mediante ejemplos prácticos sobre nuestra base de datos de Contoso, que creo que es la mejor forma de comprender el uso de la misma.
¿Qué es CALCULATETABLE? Es una función que evalúa una expresión de tabla en un contexto de filtro modificado. Y os estaréis preguntando, ¿y qué diferencia hay con la función CALCULATE? Pues prácticamente ninguna, ya que hacen casi exactamente lo mismo salvo que la función CALCULATE modifica el contexto de filtro aplicado a una expresión que devuelve un valor escalar, mientras que CALCULATETABLE devuelve una tabla. Antes de seguir, si no tienes claro lo que es el contexto de fila y filtro te recomiendo que te pases primero por el post en el que hablo de ello, te dejo aquí el filtro. Y también te recomiendo que le eches un vistazo al post sobre el orden de filtrado de CALCULATE aquí.
Una vez contextualizada la función CALCULATETABLE, ¿cuál es su sintaxis?
El primer argumento es la expresión que en este caso es la tabla que se va a evaluar y después de esa primera expresión vienen N argumentos, cada argumento sería un filtro. Insisto como con la función CALCULATE, que el nombre <filter> que no os confunda con la función FILTER ¿de acuerdo?
Bien, una vez visto la parte teórica, vamos a meternos en harina con la práctica que es la más interesante. Vamos a crear una tabla con la función CALCULATETABLE, la cual sobre la tabla de FactOnlineSales, vamos a pasarle como argumento de filtro que el ID Almacen sea 199, para ello vamos a “Modelado - Nueva Tabla”
Y escribimos la siguiente sentencia:
Validamos y lo que nos devuelve es la una nueva tabla, con 1.316.347 filas cuyo ID Almacen es 199:
Y si vamos a la tabla FactOnlineSales, el número de filas es de 3.626.523.
¿Qué está ocurriendo? Nos está generando una nueva tabla modificando el contexto de filtro.
Ahora, si habéis leído el post de la función FILTER, me diréis, las dos funciones hacen lo mismo Javi… Y yo os pregunto, ¿estáis seguros? Vamos a verlo con el siguiente ejemplo:
Validamos y lo que nos devuelve es la una nueva tabla, con 1.316.347 filas cuyo ID Almacen es 199:
En un principio, y a la vista de los resultados obtenidos, ¿se podría decir que las dos funciones realizan lo mismo? La respuesta es No… (cortocircuito mental) ¿Cómo me puedes decir que no hacen lo mismo si arrojan el mismo resultado? Bien, el motivo es que CALCULATETABLE evalúa primero el contexto de filtro y luego evalúa la expresión (de ahí que insistiera en que leer el post de Orden de filtrado de la función Calculate) mientras que la función FILTER, como comentamos en el post relativo a FILTER, pertenece al grupo de las funciones denominadas Iteradores. Las funciones del iterador enumeran todas las filas de una tabla determinada y evalúan una expresión dada para cada fila, es decir, recorren toda la tabla y la evalúan fila a fila en función de los argumentos de filtro que se le envían. En definitiva, la función FILTER no cambia el contexto de filtro. ¿Se ha entendido? ¿Nos hemos reconectado después del cortocircuito mental? J
Voy a intentar explicar el párrafo anterior con un ejemplo, en el que, en vez de generar una “copia” de la tabla con unos filtros determinados, vamos a generar la tabla con unas columnas específicas. Para ello, generamos la siguiente tabla partiendo de la tabla FactSalesOnline:
EL objetivo de la métrica anterior, generar una tabla en la que nos cuente el número de ventas de la ciudad Berlín.
¿Y cómo lo hace?
El primer paso, aplica el filtro de “Berlín”, que es el contexto de filtro. Como segundo paso, trata la expresión, que viene ya filtrada del paso anterior. Por lo tanto, como resultado, devuelve la tabla con una única fila con el número de ventas de la ciudad de Berlín.
Bien, ¿y qué pasa si sustituimos CALCULATETABLE por FILTER? ¿Nos devolverá el mismo resultado? La respuesta es no… Vamos a verlo:
Y el resultado que nos devuelve es:
¿Y qué nos está devolviendo? El número total de filas de la tabla FactOnlineSales. ¿Y por qué nos devuelve el número total de filas de la tabla? Por qué la función FILTER no cambia el contexto de filtro como lo cambia la función CALCULTETABLE (o CALCULATE como ya vimos).
Pero DAX, como siempre, nos sorprende y nos permite conseguir cosas desde distintos caminos. Me explico, tenemos la siguiente expresión, sin CALCULATETABLE, ¿qué resultado nos arrojará?
Efectivamente, lo mismo que la expresión de CALCULATETABLE, entonces, ¿toca de nuevo un cortocircuito mental? No, y la explicación es muy sencilla:
En la primera expresión, FILTER se evalúa después de ADDCOLUMNS y esta, itera todos las ciudades y COUNTROWS calcula el número total de ventas online porque no hay transición de contexto. Y posteriormente, FILTER selecciona la fila Berlín. Y en la segunda expresión está ocurriendo la famosa transición de contexto, de manera que conseguimos forzar que el contexto de fila de la función ADDCOLUMNS se convierta en un contexto de filtro para COUNTROWS. ¿Se entiende? Voy a explicarlo paso a paso:
Inicialmente, lo primero que se ejecuta es FILTER, que genera una tabla filtrándola por el valor en el que el nombre de la ciudad sea Berlín.
Una vez ejecutado el FILTER, el cálculo del número de filas se basa en la transición de contexto para forzar que el contexto de fila de ADDCOLUMNS se convierta en un contexto de filtro para COUNTROWS.
Conclusiones
A modo resumen sobre la función CALCULATETABLE, tres puntos a recordar:
1. Es una función similar a CALCULATE pero el resultado es una tabla y no un valor o escalar.
2. Se utiliza cuando se necesitan varios filtros, ya que la función FILTER sólo permite uno.
3. Es una función similar a RELATEDTABLE.
¡Nos vemos en los datos!