Función CALCULATE en DAX – Pt 2: Argumentos de Filtros, Faceta de Tablas.
Este artículo pertenece a la segunda parte de la serie de cuatro enfocados a documentar los cuatro pilares para dominar la función más importante del lenguaje DAX: CALCULATE, de hecho, los cuatro rubros son: Argumentos de Filtros, Transición de Contextos, Modificadores de CALCULATE y Orden de Precedencia.
— TABLA DE CONTENIDO DE ESTE ARTÍCULO
1. Generalidades de los parámetros de Filtros
a. Faceta 1: COMO FILTROS
b. Faceta 2: COMO MODIFICADOR
2. Parámetros de Filtros: Como Filtros
a. Inyección de Filtros a el Contexto de Filtro
b. Y en CALCULATE: Inyección de Varios Filtros
c. O en CALCULATE: Inyección de un Filtros con Varios Elementos
d. O en CALCULATE: De Columnas Diferentes
i. Opción No. 1: PELIGROSA
ii. Opción No. 2: Cardinalidad de Columna Alta
iii. Opción No. 3: Cardinalidad de Columna Baja
iv. Opción No. 4: Columnas Diferentes en Tablas Diferentes
Al igual que el primer manuscrito de la función CALCUALATE es bueno recapitular dos puntos claves antes entrar en materia:
En primer lugar, esta serie de artículos esta creado a partir de la ficha técnica de la Carta DAX de CALCULATE: Mago de la Modificación de Contextos.
Por lo que te recomiendo que la descargues y las tengas a la mano siempre si eres una persona que trabaja frecuentemente con DAX, es más imprímela.
DESCARGAR CARTAS DAX: CALCULATE MAGO DE LA MODIFICACIÓN DE CONTEXTOS
En segundo lugar, estos artículos aportan mucha luz si tienes un bagaje previo sobre el lenguaje DAX, contexto de evaluación, así como un estudio de la función CALCULATE, en resumidas cuentas, estos manuscritos no son para ti si arrancas desde cero en DAX y CALCULATE, si es verdad, que te pueden dar una idea con meridiana claridad, a pesar de ello, muchas cosas te sonarán a marciano C2 y el impacto de diversas implicaciones pasarán desapercibidas.
Si quieres un estudio desde cero, profundo, detallado y altísimo impacto en CALCULATE te recomiendo que hagas nuestro:
Énfasis en CALCULATE y CALCULATETABLE
Una capacitación OnLine y 100% en vivo de 6 horas, donde la apabullante complejidad de CALCULATE la simplificamos a 4 pilares sencillos.
Sus ediciones ocurren esporádicamente para brindar una experiencia lo más personalizada posible, vista la web y lee lo que dicen nuestros antiguos participantes [Visitar Web del Énfasis en CALCULATE].
Generalidades de los Parámetros de Filtro
Este conjunto de parámetros de la función CALCULATE tiene dos facetas: (1) Cómo Filtro y (2) Como Modificador.
Faceta 1: COMO FILTROS
Expresión tabular que representa un filtro, el cual se inyecta como nueva restricción para el contexto. Comúnmente, esta expresión de tabla se indica como una expresión booleana (TRUE/FALSE), no obstante, no es más que un azúcar sintáctico (syntax sugar) para hacer las expresiones tabulares más fáciles de leer:
• Tipo: Opcional
• Atributo: Repetible
Faceta 2: CÓMO MODIFICADOR
Mediante la ayuda de unas funciones especiales llamadas modificadores, el parámetro ya no actúa como filtro para ser inyectado al contexto, sino que cambia su comportamiento para manipular el modelo de datos, así:
• Cambios en la arquitectura de las relaciones mediante: USERELATIONSHIP para cambios en el tipo de relación y/o CROSSFILTER para cambios en e filtro cruzado o desactivar una relación.
• Cambios en la estructura original del contexto mediante:
(1) ALL, ALLEXCEPT, ALLNOBLANK y REMOVEFILTERS para remover filtros del contexto de filtro
(2) ALLSELECTED para restaurar filtros en el contexto de filtro, y
(3) KEEPFILTERS para mantener filtros nativos del contexto de filtro (aunque este último es propiamente un modificador de parámetro -Véase las observaciones-)
En el presente artículo brindaremos detalles de los parámetro de filtros en su primera faceta, cómo filtros, y en el siguiente hablaremos de su faceta cómo modificador.
Recordemos:Parámetro = Argumento.
Parámetros de Filrtos: Cómo Filtros
La primera faceta la cual puede tener cualquier parámetro de filtro de CALCULATE es como filtro o tabla, es con toda seguridad la más utilizada cuando se incia con el estudio de la función CALCULATE
Inyección de Filtros a el Contexto de Filtro
Si se desea inyectar un filtro adicional al contexto, a menudo se expresa como expresión booleana (TRUE/FALSE), por ejemplo, si desea agregar un filtro para el SKU con nombre CB01, se haría así:
IngCB01 :=
CALCULATE ( [IngTot]; Pedidos[SKU] = «CB01» )
No obstante, no se debe olvidar que la expresión: Pedidos[SKU] = «CB01» es solo una notación de tipo azúcar sintáctico para hacer la expresión más dulce, por esto, dicha expresión se convierte realmente en: FILTER (ALL (Pedidos[SKU) ; Pedidos[SKU] = «CB01») con lo cual la medida IngCB01 es en realidad:
IngCB01 :=
CALCULATE ( [IngTot]; FILTER ( ALL ( Pedidos[SKU] ); Pedidos[SKU] = «CB01» ) )
La syntax sugar (azúcar sintáctico) no tiene ninguna diferencia entre rendimiento y procesamiento interno, es exactamente lo mismo, sin embargo, es recomendable utilizar la syntax sugar siempre que sea posible sin perder de vista en ningún momento la expresión tabular detrás que la compone.
Y en la Función CALCULATE: Inyección de Varios Filtros
Si se desea inyectar varios filtros al contexto que actúen como una conjunción lógica, dicho de otro modo, como un “y”, cada filtro se debe indicar en su propio parámetro de filtro.
Cuando corresponde a elementos de columnas diferentes, su uso es intuitivo:
• Ejemplo:
IngCB01 :=
CALCULATE ( [IngTot]; Pedidos[SKU] = «CB01»; Pedidos[País] = «Colombia» )
A razón de lo anterior, se puede deducir que filtros que afecten a la misma columna con un solo elemento, y que, se han implementado en diferentes parámetros de CALCUALTE, siempre retornaran vacío.
• Ejemplo:
IngVacío :=
CALCULATE ( [IngTot]; Pedidos[SKU] = «CB01»; Pedidos[SKU] = «CC01» )
No se debe asumir siempre que varios argumentos de filtros que afecten a la misma columna van a retornar vacío, debido a que la operación que se realiza entre ellos es la intersección de sus elementos antes de la aplicación al modelo, por lo tanto, si comparten elementos si devuelven algún valor.
• Ejemplo:
IngCB01 :=
CALCULATE (
[IngTot];
Pedidos[SKU] IN { «CB01»; «CC01» };
Pedidos[SKU] IN { «L07»; «CB01» }
)
— la intersección de los elementos de los dos filtros es CB01
La medida IngCB01 es orientada a ilustrar académicamente el comportamiento de la intersección de una manera más visual. Una medida con mayor probabilidad de aplicación con la ayuda de la intersección puede ser como sigue:
• Ejemplo:
IngEntre30y50 :=
CALCULATE ( [IngTot]; Pedidos[Ingresos] >= 30; Pedidos[Ingresos] <= 50 )
— Especialmente útil para desigualdades
La descripción hasta aquí corresponde a cómo interactúan filtros generados por CALCULATE, lo que nos lleva a cómo interactuar los filtros creados por CALCULATE (programables) con los filtros nativos (automáticos).
Se debe tener presente que, si en el contexto de filtro original hay un filtro que afecte a la misma columna por uno inyectado por los parámetros de filtros de CALCULATE, entonces, el de CALCULATE se impone sobre el nativo sobrescribiéndolo. La manera de evitar este comportamiento y hacer que los dos convivan, es utilizando un modificador de parámetro de CALCULATE, particularmente: KEEPFILTERS.
• Ejemplo:
IngEntre30y50 :=
CALCULATE ( [IngTot]; Pedidos[SKU] = «CB01»; KEEPFILTERS ( Pedidos[País] = «Colombia» ) )
O en a la Función CALCULATE: Inyección de Filtros con Varios Elementos
Si se desea inyectar un filtro al contexto que actúen como una disyunción lógica, dicho de otro modo, como un “O”, se debe indicar en un sólo parámetro donde el filtro tenga en sus elementos los valores que constituyen el O.
• Por ejemplo: Una medida que devuelva los ingresos para los productos: CB01, CCO1 y L02; puede ser escrita:
IngCB01oCC01oL02 :=
CALCULATE ( [IngTot]; Pedidos[SKU] IN { «CB01»; «CC01»; «L02» } )
La expresión de la medida también puede ser escrita:
IngCB01oCC01oL02 :=
CALCULATE (
[IngTot];
Pedidos[SKU] = «CB01»
|| Pedidos[SKU] = «CC01»
|| Pedidos[SKU] = «L02»
)
— incluso puede ser escrita con dos OR anidados.
O en la Función CALCULATE de Columnas Diferentes
Aplicar un O de elementos de columnas diferentes no es posible con azúcar sintáctico, con la cual, la siguiente expresión no es válida.
• Ejemplo:
IngCB01oColombia :=
CALCULATE ( [IngTot]; Pedidos[SKU] = «CB01» || Pedidos[País] = «Colombia» )
— Esta expresión no es válida: ERROR!
En este caso, la expresión tabular debe ser redactada de forma explícita, una posibilidad puede ser:
i. Opción No. 1: PELIGROSA
IngCB01oColombia :=
CALCULATE (
[IngTot];
FILTER ( Pedidos; Pedidos[SKU] = «CB01» || Pedidos[País] = «Colombia» )
)
— Esta expresión es válida: pero NO RECOMENDABLE.
Empero, ES UNA EXPRESIÓN PELIGROSA, ya que es un filtro de tabla y no de columna, alto impacto en el rendimiento y puede arrojar valores imprecisos, en definitiva: una muy mala práctica…
…Una opción segura y mucho más apropiada sería como sigue:
ii OPción No 2: Cardinalidad de Columna Alta
IngCB01oColombia :=
CALCULATE (
[IngTot];
FILTER (
ALL ( Pedidos[SKU]; Pedidos[País] );
Pedidos[SKU] = «CB01»
|| Pedidos[País] = «Colombia»
)
)
Se ha utilizado ALL con dos columnas para crear la lista de combinaciones existentes de las columnas proporcionadas en sus parámetros. [Véase la ficha técnica de ALL]. La cardinalidad del filtro puede ser más pequeña que el producto cartesiano de los elementos de las columnas.
Si la cardinalidad de las columnas es pequeña, la expresión anterior puede ser de un rendimiento bajo, puesto que ALL debe escanear toda la tabla buscando las combinaciones; para dicho caso, una alternativa es la siguiente:
iii. Opción No 3: Cardinalidad de Columna Baja
IngCB01oColombia :=
CALCULATE (
[IngTot];
FILTER (
CROSSJOIN ( ALL ( Pedidos[SKU] ); ALL ( Pedidos[País] ) );
Pedidos[SKU] = «CB01»
|| Pedidos[País] = «Colombia»
)
)
— Recomendable para cardinalidad de columnas baja.
Con la función CROSSJOIN se obtiene todas las posibles combinaciones sobre todos los valores de las columnas, independiente si las combinaciones existen o no en el registro; en este caso, la cardinalidad del filtro es igual al producto cartesiano de los elementos de las columnas. [Véase la ficha técnica de la función CROSSJOIN].
Opción No 4: Columnas Diferentes en Tablas Diferentes
Si la aplicación del “O” se desea de columnas en tablas diferentes, la opción de la función ALL ya no es posible, puesto que únicamente admite columnas de la misma tabla, para esta situación se debe recurrir a la función SUMMARIZE.
La función SUMMARIZE genera la lista de combinaciones entre dos o más columnas, y se pueden utilizar columnas de diferentes tablas siempre y cuando estén relacionadas de muchos a uno y que se puedan acceder por cascada.
• Ejemplo:
IngCB01oColSMZ :=
CALCULATE (
[Ing];
FILTER (
SUMMARIZE ( Pedidos; Pedidos[Pais]; SKUProductos[NombreProducto] );
Pedidos[Pais] = «Colombia»
|| SKUProductos[NombreProducto] = «Batman Begins»
)
)
— Cardinalidad menor al producto cartesiano. pero se escanea la tabla — completa en busca de las combinaciones. lo cual es
— contraproducente para el rendimiento cuando las columnas tienen
— baja cardinalidad y la tabla es de un número de registros alto.
Cualquier expresión tabular es legítima en los parámetros de filtros de la función CALCULATE y no se limita a las funciones previamente señaladas, los ejemplos clásicos son las funciones de inteligencia de tiempo, como: DATESYTD, DATESBETWEEN, DATEADD, LASTNONBLANK, etc., Etc. Pero también funciones tabulares como: ADDCOLUMNS, EXCEPT, INTERSECT, ROW, SELECTCOLUMNS, UNION, VALUES, etc., Etc.
De hecho, también se puede trabajar con filtros arbitrarios, pero ello es temátoca de otro momento
Bueno eso est todo de mi parte mil gracias por leerme, nos vemos en la tercera entrega de la función CALCULATE
— Miguel