La idea
DAX hace dos tareas distintas, y en pantalla se ven casi igual. Escribes Nombre = expresión,
pulsas Enter y aparece algo nuevo en el panel Data. Pero el motor trata a ambas de forma opuesta.
- Una columna calculada se evalúa una vez por fila, cuando los datos se cargan o se actualizan. El resultado se guarda en la tabla y ocupa memoria como cualquier otra columna.
- Una medida se evalúa una vez por celda, cuando se dibuja un visual, bajo los filtros que lleva esa celda. No se guarda nada; es una fórmula esperando a que le pregunten.
Una regla elige entre ellas: si necesitas agrupar, filtrar o segmentar por ello, tiene que ser una columna. Si necesitas sumarlo o promediarlo, tiene que ser una medida.
Figura 1
Una columna calculada: un valor por fila, guardado en la tabla
| product_id | name | unit_price | Price Band |
|---|---|---|---|
| 101 | Vale Velvet Loveseat | 1659.00 | Premium |
| 102 | Alder Oak Coffee Table | 919.00 | Premium |
| 121 | Bramble Ceramic Floor Lamp | 31.99 | Everyday |
| 154 | Vale Enamel Bowl Set | 11.99 | Everyday |
| 194 | Chester Brass Wall Mirror | 159.00 | Premium |
- Una columna calculada se escribe una vez y se evalúa para cada fila de su tabla, una a una. DAX llama contexto de fila a la fila que se está visitando.
- Para la fila 101 la fórmula ve solo el
unit_pricede esa fila, 1659.00. La prueba>= 100es verdadera, así que la celda es Premium. - Luego la siguiente fila: 31.99 es menos de 100, así que Everyday. El resultado se guarda en la tabla como cualquier otra columna y solo se recalcula al actualizar.
- Como Price Band ya son datos reales, puedes ponerla en la fila de una matriz, en una segmentación o en un filtro. Una medida no podría.
Por qué existe
Una hoja de cálculo tiene un solo tipo de fórmula: vive en una celda y muestra un valor. Las tablas de Power BI tienen miles o millones de filas, y sus preguntas son de dos tipos distintos.
Algunas preguntas son sobre una fila: "¿es premium este producto?", "¿en qué mes fue este pedido?", "¿cuánto costó esta línea?". Tienen una respuesta por fila y esa respuesta no cambia al mirar la fila desde otro gráfico. Eso es una columna.
Otras preguntas son sobre un conjunto de filas: "¿cuál es nuestro valor promedio de pedido en el canal web?". La respuesta depende de qué filas entreguen el visual, las segmentaciones y el encabezado de fila. No se puede guardar, porque no es un solo número. Eso es una medida.
Confundirlas tiene costes previsibles. Una razón construida como columna devuelve un valor por fila que la matriz solo puede sumar o promediar, y eso es incorrecto. Una banda construida como medida no puede ir en una fila ni en una segmentación, porque una medida no es una columna por la que agrupar.
Cómo funciona por dentro
Contexto de fila: la fila actual
Cuando corre una columna calculada, DAX visita las filas de la tabla una tras otra. En cada
parada, esa fila es el contexto de fila (row context): products[unit_price] significa el
precio de esa fila. Por eso IF, SWITCH, YEAR y MONTH funcionan directamente en una
columna. Necesitan un valor, y el contexto de fila lo aporta.
El contexto de fila no lleva ningún filtro. Si una columna de orders llama a
SUM(order_items[line_total]), devuelve el total general en cada fila, porque el pedido actual no
filtra las líneas. Para que una fila actúe como filtro hace falta CALCULATE, que es el tema del
capítulo siguiente.
Contexto de filtro: las filas de la celda
Una medida parte de la celda. El encabezado de fila, el de columna, las segmentaciones y los filtros de página forman el contexto de filtro (filter context), y la expresión de la medida corre sobre las filas que sobreviven.
Figura 2
Una medida: se recalcula en cada celda a partir de las filas de esa celda
| order_id | channel | order_total |
|---|---|---|
| 8749 | web | 514.98 |
| 8750 | web | 192.59 |
| 8751 | app | 1483.99 |
| 8752 | web | 795.94 |
| 8753 | app | 3111.88 |
| 8754 | web | 1314.77 |
| 8757 | app | 55.97 |
| channel | Sales | Orders | Average Order Value |
|---|---|---|---|
| web | 2818.28 | 4 | 704.57 |
| app | 4651.84 | 3 | 1550.61 |
| Total | 7469.12 | 7 | 1067.02 |
- Siete pedidos. Una medida no está guardada en ninguno; solo existe cuando una celda la pide.
- La fila web filtra los pedidos a channel = web: cuatro pedidos.
Salessuma sus totales, 2818.28,Orderscuenta 4, y DIVIDE da 704.57. - La fila app ejecuta la misma fórmula sobre otro conjunto de filas: tres pedidos, 4651.84 en ventas, 1550.61 cada uno.
- La fila Total no tiene filtro de canal: los siete pedidos, 7469.12 entre 7 son 1067.02. Es la medida evaluada otra vez, no la suma ni el promedio de las filas de arriba.
De aquí salen dos detalles. Primero, una medida nunca lista filas: SUM, COUNTROWS,
DISTINCTCOUNT, AVERAGE, MIN y MAX reducen una columna o tabla a un solo número. Segundo,
la fila Total no es una suma. Es la medida sin el filtro del encabezado de fila, y para una razón
eso da una respuesta distinta de sumar las filas.
Seguir una relación en una columna
Una columna solo puede leer su propia fila, pero el modelo tiene tablas relacionadas. RELATED
lee una columna del lado uno para la fila actual:
Line Cost = order_items[quantity] * RELATED(products[unit_cost]). Necesita contexto de fila y
sigue la relación del lado muchos al lado uno.
Figura 3
RELATED: una fila que sube hasta su producto
products
- product_id
- category
- unit_cost
category = "Lighting"
order_items
- order_item_id
- product_id
- quantity
- Una columna calculada
Line Costenorder_itemsnecesita elunit_costdel producto, que está en el lado 1 de la relación. - Un filtro solo puede bajar por la relación, de
productsaorder_items, nunca subir. RELATED(products[unit_cost])es distinto: sigue elproduct_idde la fila actual hasta su única fila de producto y lee el costo. Solo funciona en contexto de fila, y solo desde el lado muchos.
Medidas que llaman a medidas
Una vez que existe Sales, puedes escribir Average Order Value = DIVIDE([Sales], [Orders]).
Una referencia a una medida se escribe con corchetes y sin nombre de tabla, que es como DAX separa
a simple vista las columnas (tabla[columna]) de las medidas. Construye medidas pequeñas y luego
compónlas. Usa DIVIDE en lugar de / para que una celda sin pedidos muestre un vacío, no un
error.
Dónde crear cada una
Ambas empiezan en el mismo sitio. En Power BI Desktop, selecciona una tabla en el panel Data y elige Table tools → New column o New measure (una medida puede vivir en cualquier tabla, porque no es una columna de ella). En Table view verás los valores de una columna; nunca verás los de una medida.
Una prueba rápida antes de escribir
Hazte dos preguntas. ¿Necesito este valor en un encabezado de fila, una segmentación o un filtro? Entonces es una columna. ¿Su respuesta cambia según la celda donde está? Entonces es una medida. Una banda de precio, un mes de pedido y un costo de línea pasan la primera prueba. Clientes que compraron, rango de precios y valor promedio de pedido pasan la segunda. Si ambas respuestas son no, probablemente necesitas otra medida o ninguna.
Errores comunes
"Una medida es solo una columna que se calcula más tarde"
Son objetos distintos. Una columna es dato: tiene un valor por fila y se guarda. Una medida no tiene valor propio, solo un resultado para un contexto dado. La misma medida puede mostrar 704.57 en una celda y 1550.61 en la siguiente. Una columna no puede cambiar así.
"La haré columna para que sea más rápido"
Una columna se calcula al actualizar y ocupa memoria en cada fila, incluidas las que nadie mira. Una medida no cuesta nada hasta que una celda la pide. Para cualquier cosa que agregues, una medida suele ser más pequeña y además correcta. Recurre a una columna cuando el valor sea una propiedad de la fila y necesites agrupar o filtrar por él.
"La fila Total suma las filas de arriba"
Ejecuta la medida otra vez, sin el filtro del encabezado de fila. Para Sales el resultado
coincide con la suma. Para Average Order Value no: 1067.02 no es la suma de 704.57 y 1550.61 ni
su promedio, porque es el promedio sobre los siete pedidos.
Ponte a prueba
Una pregunta. Al responderla, la lección queda marcada en el mapa; nunca bloquea un nivel.
Correcto. Una columna calculada corre una vez por fila al actualizar, sin filtros de celda. SUM en contexto de fila ve todas las líneas y COUNTROWS(orders) todos los pedidos, así que cada fila guarda la misma razón global, y la matriz no puede volver a ejecutarla por canal.
No del todo. Los números guardados son por fila, y sumarlos o promediarlos en la matriz no equivale a las ventas entre los pedidos del canal. Una razón pertenece a una medida.Prueba otra respuesta.
No del todo. DIVIDE funciona en cualquier sitio donde funcione DAX. El problema es cuándo corre la fórmula, no qué funciones usa.Prueba otra respuesta.
No del todo. No es lo mismo: la columna es fija por fila, la medida se recalcula en cada celda. Lo que difiere no es el tiempo de actualización.Prueba otra respuesta.
Lección hecha: ya está marcada en el mapa.