Saltearse al contenido

Inteligencia temporal (YoY, PoP, YTD, móviles declarativos)

Mondrian-4 admite un elemento de schema <TimeCalc> que declara métricas comunes de inteligencia temporal. El loader del schema desazucara cada declaración en un <CalculatedMember> validado sobre [Measures] — así que usted indica lo que quiere en lugar de escribir y mantener fórmulas MDX a mano.

¿Por qué inteligencia temporal declarativa?

Sin <TimeCalc>, el crecimiento year-over-year requiere un miembro calculado como:

<CalculatedMember name="Revenue YoY" dimension="Measures">
<Formula>
([Measures].[Revenue] - (ParallelPeriod([Calendar].[Year], 1, [Calendar].CurrentMember),
[Measures].[Revenue]))
/ (ParallelPeriod([Calendar].[Year], 1, [Calendar].CurrentMember),
[Measures].[Revenue])
</Formula>
<CalculatedMemberProperty name="FORMAT_STRING" value="0.0%"/>
</CalculatedMember>

Con <TimeCalc> la misma métrica es:

<TimeCalc name="Revenue YoY" type="yoy" measure="Revenue"
timeDimension="Calendar" formatString="0.0%"/>

El loader genera el MDX por usted, valida que la medida y la dimensión temporal referenciadas existen, y lanza un error en tiempo de carga en lugar de producir un resultado silenciosamente incorrecto.

Requisito previo: una dimensión Time tipada

<TimeCalc> requiere que el cubo tenga una dimensión Time tipada — un <Dimension> con type="TIME" cuya jerarquía tiene niveles nombrados para year, quarter y month. El nivel year debe llevar levelType="TimeYears", y los niveles quarter y month deben llevar levelType="TimeQuarters" y levelType="TimeMonths" respectivamente. Los cálculos dentro del año (ytd, pop, rolling) requieren al menos un nivel month en la jerarquía.

Una dimensión Calendar mínima que satisface el requisito:

<Dimension name="Calendar" type="TIME" table="dim_date" key="Date">
<Attributes>
<Attribute name="Year" keyColumn="year_num" levelType="TimeYears"/>
<Attribute name="Quarter" keyColumn="quarter_key" levelType="TimeQuarters"/>
<Attribute name="Month" keyColumn="month_key" levelType="TimeMonths"/>
<Attribute name="Date" keyColumn="date_key" levelType="TimeDays"/>
</Attributes>
<Hierarchies>
<Hierarchy name="Calendar" allMemberName="All Time">
<Level attribute="Year"/>
<Level attribute="Quarter"/>
<Level attribute="Month"/>
<Level attribute="Date"/>
</Hierarchy>
</Hierarchies>
</Dimension>

Colocación en el schema

Los elementos <TimeCalc> se envuelven en un bloque <TimeCalcs> dentro de un <Cube>, al mismo nivel que <CalculatedMembers>:

<Cube name="Monthly Revenue">
<Dimensions>
<Dimension source="Calendar"/>
<!-- other dimensions -->
</Dimensions>
<MeasureGroups>
<MeasureGroup name="Revenue" table="monthly_revenue_fact">
<Measures>
<Measure name="Revenue" column="revenue" aggregator="sum"/>
</Measures>
<DimensionLinks>
<ForeignKeyLink dimension="Calendar" foreignKeyColumn="month_key"/>
</DimensionLinks>
</MeasureGroup>
</MeasureGroups>
<TimeCalcs>
<TimeCalc name="Revenue YoY" type="yoy" measure="Revenue" timeDimension="Calendar" formatString="0.0%"/>
<TimeCalc name="Revenue PoP" type="pop" measure="Revenue" timeDimension="Calendar" formatString="0.0%"/>
<TimeCalc name="Revenue YTD" type="ytd" measure="Revenue" timeDimension="Calendar"/>
<TimeCalc name="Revenue R3" type="rolling" measure="Revenue" timeDimension="Calendar" window="3" function="avg"/>
</TimeCalcs>
</Cube>

Referencia de atributos

Atributoclave XML / YAMLRequeridoDescripción
namenameEl nombre del miembro calculado generado. Aparece en [Measures] como cualquier otra medida.
typetypeEl tipo de métrica: yoy, pop, ytd o rolling. Consulte Tipos de métrica abajo.
measuremeasureEl nombre de un <Measure> existente en el cubo. El loader rechaza una medida desconocida en la carga del schema.
timeDimensiontime_dimensioncondicionalEl nombre de una dimensión type="TIME". Puede omitirse cuando el cubo tiene exactamente una dimensión TIME; requerido cuando tiene más de una.
windowwindowsolo rollingNúmero entero de períodos a incluir en la ventana móvil.
functionfunctionsolo rollingFunción de agregación sobre la ventana: sum (por defecto) o avg.
formatStringformat_stringnoCadena de formato MDX aplicada al miembro generado, por ejemplo "0.0%" o "#,###".

Tipos de métrica

yoy — crecimiento year-over-year

Informa el cambio porcentual comparado con el mismo período del año anterior.

Forma de la fórmula:

([Measures].[<measure>] -
(ParallelPeriod([<dim>].[<YearLevel>], 1, [<dim>].CurrentMember),
[Measures].[<measure>]))
/
(ParallelPeriod([<dim>].[<YearLevel>], 1, [<dim>].CurrentMember),
[Measures].[<measure>])

La llamada ParallelPeriod navega a la misma posición relativa un año atrás usando el nivel TimeYears. El resultado es NULL para el primer año completo de datos (sin año anterior disponible).

pop — crecimiento period-over-period

Informa el cambio porcentual comparado con el período inmediatamente anterior (el período justo antes del actual en el mismo nivel).

Forma de la fórmula:

([Measures].[<measure>] -
(PrevMember([<dim>].CurrentMember), [Measures].[<measure>]))
/
(PrevMember([<dim>].CurrentMember), [Measures].[<measure>])

PrevMember retrocede una posición en el orden natural de la dimensión. Los resultados son NULL para el primer miembro de un nivel (sin predecesor).

ytd — acumulado year-to-date

Informa el valor acumulado de la medida desde el inicio del año actual hasta el período actual.

Forma de la fórmula:

Aggregate(Ytd([<dim>].CurrentMember), [Measures].[<measure>])

Ytd() devuelve el conjunto de todos los períodos desde el primer período del año actual hasta el período actual. Aggregate aplica la agregación nativa de la medida (típicamente sum) sobre ese conjunto.

rolling — ventana móvil

Informa el agregado de la medida sobre los últimos window períodos, usando sum o avg.

Forma de la fórmula (avg, window=3):

Avg(LastPeriods(3, [<dim>].CurrentMember), [Measures].[<measure>])

Forma de la fórmula (sum, window=N):

Sum(LastPeriods(N, [<dim>].CurrentMember), [Measures].[<measure>])

LastPeriods(N, member) devuelve el conjunto de los N períodos que terminan en el miembro actual. Si hay menos de N períodos disponibles (por ejemplo, al inicio del historial de datos), la ventana se reduce a tantos períodos como existan — no rellena con ceros.

Comportamiento de validación

El loader es fail-closed: la carga del schema se aborta con un mensaje de error claro si se detecta alguna de las siguientes condiciones.

CondiciónError
measure nombra un miembro que no existe en el cuboTimeCalc "X": measure "Y" not found in cube
No se especifica timeDimension y el cubo tiene cero dimensiones TIMETimeCalc "X": cube has no TIME dimension
No se especifica timeDimension y el cubo tiene más de una dimensión TIMETimeCalc "X": cube has multiple TIME dimensions — specify timeDimension
timeDimension nombra una dimensión que no existe en el cuboTimeCalc "X": timeDimension "Y" not found
type="rolling" y window falta o no es un entero positivoTimeCalc "X": rolling type requires a positive integer window
type="yoy" pero no existe nivel TimeYears en la dimensiónTimeCalc "X": TIME dimension has no TimeYears level

No hay resultado silenciosamente incorrecto — cada mala configuración se captura antes de que se ejecute la primera consulta.

Ejemplo trabajado: ingresos mensuales de la demo Bank

La demo Bank incluye un cubo Monthly Revenue sobre una serie mensual de ingresos. Los datos crudos para dos años:

AñoMesRevenue
2024Ene100
2024Feb200
2024Mar300
2025Ene150
2025Feb250
2025Mar350

El cubo declara los cuatro tipos de <TimeCalc> contra la dimensión Calendar (Year > Quarter > Month):

<TimeCalcs>
<TimeCalc name="Revenue YoY" type="yoy" measure="Revenue" timeDimension="Calendar" formatString="0.0%"/>
<TimeCalc name="Revenue PoP" type="pop" measure="Revenue" timeDimension="Calendar" formatString="0.0%"/>
<TimeCalc name="Revenue YTD" type="ytd" measure="Revenue" timeDimension="Calendar"/>
<TimeCalc name="Revenue R3" type="rolling" measure="Revenue" timeDimension="Calendar" window="3" function="avg"/>
</TimeCalcs>

Resultados de referencia

CeldaValorCómo
Revenue YoY en [Calendar].[2025].[Q1].[Jan 2025]0.5 (50%)(150 − 100) / 100 = 0.5
Revenue PoP en [Calendar].[2024].[Q1].[Feb 2024]1.0 (100%)(200 − 100) / 100 = 1.0
Revenue YTD en [Calendar].[2024].[Q1].[Mar 2024]600100 + 200 + 300 = 600
Revenue R3 en [Calendar].[2025].[Q1].[Mar 2025]250avg(150, 250, 350) = 250

Consulta MDX de ejemplo

SELECT
{ [Measures].[Revenue],
[Measures].[Revenue YoY],
[Measures].[Revenue PoP],
[Measures].[Revenue YTD],
[Measures].[Revenue R3] } ON COLUMNS,
[Calendar].[Month].Members ON ROWS
FROM [Monthly Revenue]

Resultado parcial (2024–2025 enero hasta marzo):

MesRevenueYoYPoPYTDR3
Ene 2024100100100
Feb 2024200100.0%300150
Mar 202430050.0%600200
Ene 202515050.0%−50.0%150216.7
Feb 202525025.0%66.7%400233.3
Mar 202535016.7%40.0%750250

Los guiones (—) indican NULL — no hay datos del año anterior o no hay período predecesor disponible.

Relación con <CalculatedMembers>

Las declaraciones <TimeCalc> se desazucan en tiempo de carga en elementos <CalculatedMember> sobre [Measures]. Los miembros generados son indistinguibles de los miembros calculados escritos a mano en tiempo de consulta: aparecen en enumeraciones de miembros XMLA, responden a FORMAT_STRING, y pueden ser referenciados por otros miembros calculados.

Si necesita una fórmula que <TimeCalc> no pueda expresar — por ejemplo, una métrica mezclada personalizada o una razón multi-medida antes de una comparación temporal — use directamente un <CalculatedMember> plano. Los dos enfoques pueden coexistir en el mismo cubo.

Consulte Avanzado — Miembros calculados para la referencia completa de <CalculatedMember>.