Resolución del ejercicio

Al añadir una columna calculada vamos a trabajar, por defecto, en contexto de fila, por lo que, si queremos obtener valores resultantes de filtrar el modelo de datos, tendremos que ejecutar la transición de contexto. Esta tabla de subcategorías tiene una clave primaria (Subcategory Id):

Subcategory

por lo que podemos estar seguros de que, tras ejecutar la transición de contexto, estaremos filtrando solo una fila de la tabla.

Para la creación de la columna tenemos que obtener dos valores: las ventas de cada subcategoría y las ventas de la categoría a la que pertenezca.

Creemos una primera versión de nuestra expresión DAX usando pseudo-código:

Sales Pct = 
VAR __subcatSales = Ventas de la subcategoría siendo iterada
VAR __category = Categoría a la que pertenece la subcategoría
VAR __catSales = Ventas de la categoría “__category”
RETURN
    DIVIDE(
        __subcatSales,
        __catSales
    )

El cálculo de las ventas de la subcategoría siendo iterada es inmediato: basta con dejar que se ejecute la transición de contexto y sumar la columna Sales[Amount]. O, dicho con otras palabras, el valor que queremos puede obtenerse haciendo referencia a la medida [Sales]:

VAR __subcatSales = [Sales]

La obtención de la categoría asociada a cada subcategoría puede lograrse usando la función RELATED (pues ya sabemos que una subcategoría tiene asociada una y solo una categoría):

VAR __category = RELATED(Category[Category])

Por último, el cálculo de las ventas asociadas a la categoría a la que pertenece la subcategoría siendo iterada (la categoría __category) es un poco más complejo. Pensemos qué querríamos hacer: Imaginemos el modelo de datos completamente visible (sin filtros aplicados a ninguna tabla). Ahora, el objetivo sería sumar el campo Sales[Amount] tras filtrar la tabla Category de forma que solo la fila correspondiente a __category estuviese siendo seleccionada (lo que filtraría la tabla de subcategorías, la de productos y la de ventas). Esto nos invita a hacer uso de la función CALCULATE imponiendo este filtro. Hagamos un primer intento:

Sales Pct = 
VAR __subcatSales = [Sales]
VAR __category = RELATED(Category[Category])
VAR __catSales =
    CALCULATE(
        [Sales],
        Category[Category] = __category
    )
RETURN
    DIVIDE(
        __subcatSales,
        __catSales
    )

En este código estamos intentando obtener las ventas de la categoría __category evaluando la medida [Sales] en un nuevo contexto de filtro en el que Category[Category] = __category.

Sin embargo, si creamos la columna calculada con este código obtenemos el siguiente resultado:

Sales Pct

Claramente no está funcionando. Veamos por qué: cuando ejecutamos la función CALCULATE para el cálculo de __catSales estamos ejecutando la transición de contexto (pues no olvidemos que nos encontramos en contexto de fila), por lo que el modelo de datos se va a filtrar de forma tal que, en la tabla de subcategorías, solo la fila siendo iterada va a quedar visible, y esto va a filtrar la tabla de productos y, a su vez, la de ventas. Y a este contexto de filtro le estamos añadiendo un filtro adicional que viene dado por Category[Category] = __category. Es decir, la tabla de categorías tendría ahora una única fila visible (la de la categoría que nos interesa), lo que filtra a su vez la tabla de subcategorías, pero ésta está siendo previamente filtrada debido a la transición de contexto y solo tiene una fila visible (la siendo iterada) por lo que el resultado de ambos filtros (el proveniente de Category y el generado en Subcategory por la transición de contexto), aplicados simultáneamente a Subcategory, deja en esta tabla una única fila visible: la correspondiente a la subcategoría siendo iterada. La consecuencia es que en la tabla Sales solo las ventas asociadas a la subcategoría siendo iterada están visibles. O, con otras palabras, el valor devuelto por __catSales es exactamente el mismo que el devuelto por __subcatSales.

Lo que necesitamos es imponer el filtro en la tabla Category pero asegurándonos de que la tabla Subcategory no está siendo inicialmente filtrada debido a la transición de contexto (para que sea el filtro aplicado a Category el que la filtre). Esto podemos conseguirlo haciendo uso de la función ALL:

Sales Pct = 
VAR __subcatSales = [Sales]
VAR __category = RELATED(Category[Category])
VAR __catSales =
    CALCULATE(
        [Sales],
        Category[Category] = __category,
        ALL(Subcategory)
    )
RETURN
    DIVIDE(
        __subcatSales,
        __catSales
    )

Ahora -en el cálculo de __catSales- ya podemos estar seguros de que la tabla Sales está siendo filtrada de forma que las ventas visibles son todas las asociadas con la categoría que nos interesa. El resultado obtenido es el buscado:

Sales Pct

Vemos que, por ejemplo, las tres subcategorías asociadas a la categoría cuyo identificador es 1 (en rojo en la anterior imagen) suponen el 42%, el 45% y el 12% del total de ventas de dicha categoría.