Cálculo de totales acumulados

Un escenario frecuente es aquel en el que queremos calcular el total acumulado, incluyendo todos los datos hasta una cierta fecha y no solo los implicados en el contexto de filtro actual. Por ejemplo, si suponemos la existencia de una tabla de ventas Sales que contiene una columna Amount con la cifra de ventas, podríamos definir una medida que calculase la suma de esta columna con la siguiente expresión DAX:

Sales = SUM(Sales[Amount])

Lógicamente, esta medida se va a adaptar al contexto de filtro, por lo que si la llevamos a una matriz en la que se esté desagregando las ventas por año:

Sales by year

...vemos que, para cada año, la cifra de ventas mostrada incluye solo las ventas de dicho año.

Lo que querríamos sería que, en cada evaluación de la medida, el período temporal considerado comenzase el primer día para que el hubo ventas (supongamos que el 1 de enero de 2015) y se extendiese hasta la última fecha del "período actual". Por ejemplo, en la cifra correspondiente al año 2018 el período actual es el correspondiente a los 365 días de dicho año. Pues bien, para el cálculo del acumulado para dicho año querríamos que se considerase el período comprendido entre el 1 de enero de 2015 y el 31 de diciembre de 2018. Es decir, escrito en pseudo-código:

Accumulated sales = 
CALCULATE(
    [Sales],
    Período entre la primera fecha disponible y la última fecha del contexto actual
)

El período en cuestión puede calcularse usando la función DATESBETWEEN que devuelve el conjunto de fechas entre dos dadas. Si el calendario está contenido en la tabla Calendar, tendríamos, por lo tanto, que codificar la siguiente medida:

Accumulated sales = 
CALCULATE(
    [Sales],
    DATESBETWEEN(
        'Calendar'[Date],
        Primera fecha disponible,
        Última fecha del contexto actual
    )
)

Ahora bien, es el cálculo de esas dos fechas lo que resulta más complejo, pues queremos que la primera fecha ("Primera fecha disponible") sea absoluta y haga referencia a la primera fecha disponible en el calendario, mientras que la segunda ("Última fecha del contexto actual") queremos que se adapte al contexto.

Para la obtención de la primera fecha disponible en el calendario deberemos asegurarnos de que no se están aplicando filtros al mismo, para lo que podemos usar la función ALL (lo que va a devolver una tabla). Y para la extracción de la primera fecha disponible de dicha tabla no podemos usar la función MIN pues ésta exige una columna como argumento, de forma que tendremos que usar la función FIRSTDATE, que sí acepta una tabla como argumento y devuelve otra tabla (con la fecha más antigua disponible), tabla que podemos pasar a la función CALCULATE como argumento de filtro:

FIRSTDATE(ALL(Sales[Order Date]))

Para el cálculo de la última fecha del contexto actual no tenemos más que utilizar la función MAX pasando como argumento la columna temporal que está desagregando nuestro objeto visual: la columna 'Calendar'[Date]. Es decir, la última fecha del contexto actual vendría dada por:

MAX('Calendar'[Date])

Es decir, la expresión

DATESBETWEEN(
    'Calendar'[Date],
    FIRSTDATE(ALL(Sales[Order Date])),
    MAX('Calendar'[Date])
)

...va a devolver el conjunto de fechas del calendario entre la más antigua disponible y la última implicada en el contexto actual. Podemos escribir, por lo tanto, la medida que devuelve las ventas acumuladas:

Accumulated sales =
CALCULATE(
    [Sales],
    DATESBETWEEN(
        'Calendar'[Date],
        FIRSTDATE(ALL(Sales[Order Date])),
        MAX('Calendar'[Date])
    )
)

Si quisiéramos utilizar variables para hacer más legible el código, podríamos crear dos variables, __firstdate y __lastDate conteniendo las dos fechas implicadas en el código anterior:

Accumulated sales =
VAR __firstDate = FIRSTDATE(ALL(Sales[Order Date]))
VAR __lastDate = MAX('Calendar'[Date])
RETURN
    CALCULATE(
        [Sales],
        DATESBETWEEN(
            'Calendar'[Date],
            __firstDate,
            __lastDate
        )
    )

Ahora, si llevamos la medida anterior a nuestra matriz, comprobamos que se están acumulando las ventas tal y como queríamos:

Accumulated sales by year

Y, por supuesto, si mostramos la matriz desagregada por cualquier otro nivel de nuestra jerarquía temporal, por trimestres, por ejemplo, el cálculo de las ventas acumuladas sigue realizándose correctamente:

Accumulated sales by quarter
Funciones DAX involucradas
Dificultad
Intermedia
Enviado por admin el Lun, 03/12/2018 - 20:19