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!