Power BI · Capítulo 6 · Lección de conceptos · 7 min de lectura

Por qué la inteligencia de tiempo necesita una tabla Date

TOTALYTD y SAMEPERIODLASTYEAR no miran tus pedidos. Eligen fechas de una tabla calendario y las ponen en el filtro, así que el calendario debe tener todos los días, estar relacionado y estar marcado.

La idea

La inteligencia de tiempo suena como si DAX leyera tus ventas y entendiera el tiempo. No es así. Funciones como TOTALYTD, SAMEPERIODLASTYEAR y DATEADD trabajan con fechas, y las sacan de un solo sitio: una tabla Date, un calendario con una fila por día.

Lo que hacen es poco. Miran las fechas que muestra la celda actual, construyen otro conjunto de fechas (del 1 de enero hasta hoy, los mismos días un año antes, el mes anterior) y ponen ese conjunto en el filtro antes de que corra la medida. La medida, [Sales], no cambia nunca. Solo cambian los días que recibe.

Figura 1

Un calendario hecho con las fechas de pedidos tiene huecos

Días que aparecen en orders[order_date], finales de enero de 2024
order_dateorders
2024-01-275
2024-01-2812
2024-01-299
2024-01-318
2024-02-017
Una tabla 'Date' de verdad: una fila por día
DateYear MonthWeekday Number
2024-01-272024-016
2024-01-282024-017
2024-01-292024-011
2024-01-302024-012
2024-01-312024-013
2024-02-012024-024

Paso 1 de 3 En 2024 la tienda no recibió ningún pedido el 30 de enero, así que esa fecha nunca aparece en orders[order_date]. Los 1,095 días con pedidos de la tienda forman un calendario con un hueco.

  1. En 2024 la tienda no recibió ningún pedido el 30 de enero, así que esa fecha nunca aparece en orders[order_date]. Los 1,095 días con pedidos de la tienda forman un calendario con un hueco.
  2. La inteligencia de tiempo supone que el calendario está completo. Un periodo desplazado un año atrás o un mes adelante puede caer en una fecha que no existe, y el resultado sale mal o en blanco.
  3. Una tabla 'Date' se construye por separado, con una fila por cada uno de los 1,096 días entre 2023-01-01 y 2025-12-31. El 30 de enero está ahí, con cero ventas.

Por qué existe

"¿Cómo vamos comparado con el año pasado?" es la primera pregunta que hace un gerente. En una hoja de cálculo la respondes a mano: copias las ventas, desplazas una columna, restas. En Power BI pides "el mismo periodo del año pasado" y tiene que saber qué es un periodo. Las filas de pedidos no pueden decirlo. Un año, un mes, un día de la semana o un festivo no son propiedades de una venta; son propiedades de un día, y el calendario es donde viven los días.

Por eso el modelo recibe una tabla extra, hecha para esto, y toda función que habla de tiempo lee de ella. Un solo calendario también significa una sola definición de "mes" para todos los informes.

Cómo funciona por dentro

Tres reglas para el calendario

  1. Continuo. Una fila por cada día, sin huecos, desde la primera fecha que necesites hasta la última. Constrúyelo a partir de un rango (el de la tienda va del 2023-01-01 al 2025-12-31), no a partir de las fechas de tus pedidos.
  2. Relacionado. 'Date'[Date] tiene una fila por día, así que está en el lado 1 de una relación con orders[order_date], como en la estrella del capítulo de modelado de datos.
  3. Marcado. Selecciona la tabla y usa Table tools → Mark as date table, y luego elige la columna Date. Power BI comprueba que tenga fechas únicas, y DAX aprende cuál es la tabla calendario.

Todo lo demás de la tabla sirve para segmentar: Year, Quarter, Month Number, Month, Year Month y Weekday Number. Puedes añadir las tuyas como columnas calculadas, como una marca de fin de semana con IF.

Acumulado del año, paso a paso

TOTALYTD es CALCULATE con un conjunto de fechas ya preparado. Para la fila de marzo toma el último día visible, construye del 1 de enero al 31 de marzo y evalúa [Sales] sobre ellos. Mes a mes, la medida traza una línea que se reinicia cada enero.

Figura 2

Sales YTD, 2025: un acumulado que se reinicia cada enero

$0 $625,000 $1,250,000 $1,875,000 $2,500,000 Sales YTD Jan: $150,571Feb: $250,474Mar: $417,261Apr: $606,996May: $813,465Jun: $1,026,527Jul: $1,218,494Aug: $1,401,481Sep: $1,544,860Oct: $1,719,459Nov: $2,011,823Dec: $2,300,170 JanMarMayJulSepNov plan: $1M en junio

Paso 1 de 4 Sales YTD = TOTALYTD([Sales], 'Date'[Date]). Enero muestra las ventas de enero, $150,571, porque el acumulado del año empieza el 1 de enero.

  1. Sales YTD = TOTALYTD([Sales], 'Date'[Date]). Enero muestra las ventas de enero, $150,571, porque el acumulado del año empieza el 1 de enero.
  2. Marzo muestra $417,261: enero, febrero y marzo sumados. La medida es la misma en cada celda; lo que crece son las fechas que recibe.
  3. Junio cruza la línea del plan de $1 millón: $1,026,527 al 30 de junio.
  4. Diciembre muestra el año completo, unos $2.3 millones, y en enero la línea vuelve a empezar desde cero.

La familia tiene la misma forma. DATESMTD construye los días desde el día 1 del mes. TOTALQTD lo hace para el trimestre. DATESYTD devuelve el conjunto de fechas para que lo uses tú dentro de CALCULATE, que es como se construye una medida como el acumulado del año pasado.

Desplazar: el mismo periodo del año pasado

SAMEPERIODLASTYEAR('Date'[Date]) toma los días visibles y mueve cada uno un año atrás. Para la fila de marzo de 2025 eso significa marzo de 2024. CALCULATE([Sales], SAMEPERIODLASTYEAR('Date'[Date])) devuelve $161,477 donde [Sales] devuelve $166,787, así que el crecimiento es DIVIDE([Sales] - [Sales PY], [Sales PY]) = 3.3%. DATEADD('Date'[Date], -1, MONTH) desplaza el paso que le indiques, que es como se hace una medida del mes anterior.

Dos cosas lo mantienen seguro. Usa DIVIDE, porque el primer año de datos no tiene año previo y la división debe mostrar un vacío, no un error. Y escribe el crecimiento una sola vez con variables (VAR), para que la medida desplazada se calcule una única vez.

Por qué importa que esté "marcada"

La fila de la matriz también trae sus propios filtros de fecha, Year Month = 2025-03. Que las fechas nuevas los reemplacen o se sumen a ellos depende de la marca.

Figura 3

Cómo construye TOTALYTD su filtro para la fila 2025-03

  1. Filtros de la celda Year = 2025, Year Month = 2025-03
  2. Última fecha visible 31 de marzo de 2025
  3. Construir las fechas del 1 de enero al 31 de marzo
  4. Ponerlas en el filtro sobre 'Date'[Date]
  5. Evaluar [Sales] sobre esos días

Paso 1 de 5 La fila trae sus propios filtros: la segmentación de Year y el Year Month de la fila de la matriz.

  1. La fila trae sus propios filtros: la segmentación de Year y el Year Month de la fila de la matriz.
  2. TOTALYTD mira las fechas visibles y toma la última, el 31 de marzo.
  3. A partir de esa fecha construye los días desde el 1 de enero del mismo año hasta ella.
  4. Con el calendario marcado como tabla de fechas, las fechas nuevas reemplazan los filtros de fecha de la fila. La suma corre entonces sobre enero a marzo: $417,261.
  5. Sin marcar, el Year Month = 2025-03 de la fila sobrevive junto a las fechas nuevas. Se cruzan y queda solo marzo: $166,787, igual que Sales.

Cuando la tabla está marcada, DAX conoce el calendario y borra todos los filtros de fecha antes de aplicar los nuevos. Cuando no está marcada, los filtros viejos se quedan, y un acumulado de marzo se construye de enero a marzo y marzo: solo marzo. La señal inequívoca es que la fila Total es correcta y todas las demás son iguales a su propio mes. Ese es todo el error de "¿por qué mi YTD es solo el mes?".

Otros calendarios

Un año fiscal que empieza en julio usa la misma tabla. TOTALYTD acepta un tercer argumento opcional, la fecha de fin de año, como en TOTALYTD([Sales], 'Date'[Date], "6/30"), y el acumulado se reinicia al día siguiente. Columnas como un año fiscal o una marca de "últimos 12 meses" son una columna calculada más en 'Date', y por eso vale la pena tener un calendario propio.

Errores comunes

"Puedo usar orders[order_date] como calendario"

Una columna de fechas de pedidos tiene una fila por pedido, no por día, y le faltan días (el 30 de enero de 2024 aquí). Las funciones de tiempo necesitan fechas únicas y completas. 'Date'[Date] es la columna que hay que darles. Si tu modelo tiene una, comprueba que sea la columna a la que apunta Mark as date table.

"Auto date/time hace innecesaria una tabla Date"

Auto date/time crea en silencio un calendario oculto para cada columna de fecha. Sirve para un gráfico puntual, pero da a cada columna de fecha su propio calendario, no puede contener tus propias columnas como un año fiscal o una marca de fin de semana, y no se comparte entre tablas. La mayoría de los modeladores lo apagan y construyen una sola tabla 'Date'.

"Las funciones de tiempo buscan las ventas del año pasado"

Buscan días. La función le entrega al motor un conjunto de fechas, y el motor filtra los hechos a través de la relación de la forma habitual. Si falta la relación con el calendario o está inactiva, las fechas se construyen bien y nunca llegan a las ventas, así que la medida devuelve el mismo número que Sales o un vacío.

Ponte a prueba

Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.

Sales YTD = TOTALYTD([Sales], 'Date'[Date]) muestra $99,903 en la fila 2025-02, lo mismo que Sales de febrero. Las filas de la matriz vienen de 'Date'[Year Month]. ¿Cuál es la causa más probable?

Elige qué puede ejecutarse en este sitio. Puedes cambiarlo cuando quieras desde "Configurar cookies", al pie de cada página.