Power BI · Fundamentos · 7 min de lectura

El esquema en estrella

Antes de la primera medida: por qué un modelo de Power BI guarda los números en una tabla de hechos y las descripciones en tablas de dimensiones, y cómo las relaciones de uno a varios llevan el filtro de una segmentación hasta los números.

La idea

Un modelo de Power BI no es una tabla enorme. Es un puñado de tablas pequeñas unidas por relaciones, y la forma que mejor funciona tiene nombre: el esquema en estrella.

En el centro hay una tabla de hechos. Tiene una fila por cada cosa que ocurrió: una línea de pedido, un clic, un pago. Sus columnas son sobre todo números que sumas (line_total, quantity) y ids que dicen quién, qué y cuándo. Alrededor están las tablas de dimensiones. Una dimensión tiene una fila por cada producto, cliente o día, y sus columnas son las palabras por las que agrupas y filtras: category, state, Year.

Dibújalo y parece una estrella: los hechos en el centro y una dimensión en cada punta.

Figura 1

Una tabla plana frente a un modelo de tablas pequeñas

Una tabla plana: cada línea de pedido con todos sus datos
order_item_idfirst_namestateproductline_total
1JasmineMABramble Ceramic Floor Lamp287.91
2JasmineMAVale Enamel Bowl Set35.97
3PaulAZVale Enamel Bowl Set47.96
4PaulAZChester Brass Wall Mirror149.00
order_items (hechos)
order_item_idorder_idproduct_idline_total
11001121287.91
2100115435.97
3100215447.96
41002194149.00
orders
order_idcustomer_id
1001125
1002156
customers (dimensión)
customer_idfirst_namestate
125JasmineMA
156PaulAZ

Paso 1 de 4 Una tabla plana: una fila por línea de pedido, con los datos del cliente copiados en cada línea.

  1. Una tabla plana: una fila por línea de pedido, con los datos del cliente copiados en cada línea.
  2. Jasmine aparece en dos filas y Paul en otras dos. Contar las filas da cuatro clientes y son dos. Si cambias un estado, tienes que cambiarlo en cada línea.
  3. Sepárala. order_items guarda solo los números y los ids. Cada cliente se escribe una vez en customers, y orders dice quién compró qué.
  4. Ahora COUNTROWS(customers) da 2, el estado vive en un solo sitio y SUM(order_items[line_total]) sigue sumando 520.84.

Por qué existe

Podrías guardarlo todo en una tabla plana, como una exportación de hoja de cálculo. Con un archivo pequeño funciona. Después los problemas se acumulan.

  • Texto repetido. El nombre y el estado de Jasmine se copian en cada línea que compró. Si corriges su estado, tienes que corregirlo en cada fila, o el informe muestra dos Jasmines.
  • Cuentas erróneas. Cuenta las filas de una tabla plana y contarás líneas, no clientes. Cada recuento de distintos se convierte en un apaño.
  • Tamaño. Power BI comprime las columnas, pero un millón de líneas con el nombre del producto copiado sigue siendo un millón de copias. Las tablas pequeñas se recorren y se actualizan más rápido.
  • Un solo sitio donde segmentar. Una única columna Year en la dimensión sirve a todas las medidas. En una tabla plana cada hecho necesitaría su propia columna de fecha.

La estrella escribe cada dato una sola vez. Por eso una medida como SUM(order_items[line_total]) puede responder "por categoría", "por estado" y "por mes" sin cambiar un solo carácter.

Cómo funciona por dentro

Claves

Las tablas se encuentran mediante claves. Una clave principal es una columna con valores únicos: customers[customer_id] tiene exactamente una fila por cliente. Una clave externa es una columna de otra tabla que repite esos valores para apuntar a una fila: orders[customer_id]. Power BI no te pide declararlas. Eliges las dos columnas al dibujar la relación y comprueba que el lado 1 sea realmente único.

Relaciones de uno a varios

Una relación une una clave con una clave externa. Un cliente tiene muchos pedidos, un pedido tiene muchas líneas, un producto aparece en muchas líneas, un día reúne muchos pedidos. Cada una es de uno a varios: el lado 1 es la dimensión y el lado muchos (*) es la tabla que apunta a ella.

Las dibujas en la Model view (el tercer icono de la barra izquierda de Power BI Desktop): arrastra una columna sobre otra, o usa Home → Manage relationships → New. El cuadro pide las dos columnas, la cardinalidad y la dirección del filtro cruzado.

Figura 2

La estrella de Harbor & Pine: una tabla de hechos y las descripciones alrededor

'Date'

  • Date
  • Year
  • Month

orders

  • order_id
  • customer_id
  • order_date
  • channel

customers

  • customer_id
  • segment
  • state

products

  • product_id
  • category
  • unit_price

order_items

  • order_item_id
  • order_id
  • product_id
  • line_total

Paso 1 de 4 order_items es la tabla de hechos: una fila por línea de pedido, con los números (line_total) y los ids que apuntan a otras tablas. Es, con diferencia, la más larga.

  1. order_items es la tabla de hechos: una fila por línea de pedido, con los números (line_total) y los ids que apuntan a otras tablas. Es, con diferencia, la más larga.
  2. products, customers y 'Date' son dimensiones: una fila por producto, cliente o día, llenas de las palabras por las que segmentas.
  3. Cada línea tiene un 1 en un extremo y un * en el otro. El lado 1 es la tabla que guarda la clave una sola vez; el lado * tiene muchas filas que apuntan a ella.
  4. orders es una pequeña tabla de cabecera entre las líneas, el cliente y el calendario. La forma sigue siendo una estrella: cada descripción está a un salto corto de los números.

Dirección del filtro

Una relación no es solo una línea. Es una tubería que lleva filtros, y en una estrella normal los lleva en un solo sentido: del lado 1 al lado muchos. Elige MA en una segmentación de estado y el filtro llega a customers, luego a orders y luego a order_items. La suma corre entonces solo sobre las líneas de MA.

Figura 3

Una segmentación por estado: el filtro corre en un solo sentido

'Date'

  • Date
  • Year
  • Month

orders

  • order_id
  • customer_id
  • order_date
  • channel

customers

  • customer_id
  • segment
  • state

state = "MA"

products

  • product_id
  • category
  • unit_price

order_items

  • order_item_id
  • order_id
  • product_id
  • line_total

Paso 1 de 3 Una segmentación elige state = "MA". El filtro cae en customers, la tabla dueña de esa columna.

  1. Una segmentación elige state = "MA". El filtro cae en customers, la tabla dueña de esa columna.
  2. Corre del lado 1 al lado *: primero a orders y luego a order_items. Solo quedan las líneas de Massachusetts para sumar.
  3. No sube de vuelta. products queda intacta, así que una segmentación de categoría sigue mostrando todas las categorías, incluso las que MA nunca compró.

Ese flujo en un solo sentido es una virtud. Hace que una medida lea la tabla de hechos siempre por un camino predecible, y que una segmentación sobre una dimensión nunca tenga dos formas de llegar a los números. El cuadro también ofrece la dirección Both. No la toques hasta que sepas decir qué camino sigue cada filtro: dos caminos entre las mismas tablas vuelven el modelo ambiguo, y Power BI lo rechaza o elige uno por ti.

Qué va dónde

Cuando encuentres una columna nueva, hazte una pregunta: ¿la sumo o agrupo por ella? Si la sumas, pertenece a un hecho (line_total). Si agrupas por ella, pertenece a una dimensión (category, state, Month). Una columna que es etiqueta y número a la vez, como unit_price, suele ser un atributo de la dimensión: describe el producto, aunque un hecho guarde el precio realmente cobrado.

Por qué el calendario es una tabla aparte

orders[order_date] ya tiene una fecha, ¿entonces para qué una tabla 'Date'? Porque un hecho solo tiene los días en que pasó algo, y una dimensión puede tener todos los días, con Year, Quarter y Month listos para agrupar. Un solo calendario sirve entonces a todas las tablas de hechos con fecha. El capítulo de inteligencia de tiempo se apoya en él.

Cuando una clave no encuentra pareja

Si un pedido apunta a un id de cliente que customers no tiene, Power BI conserva el pedido y lo archiva en una fila en blanco del lado de la dimensión. Un (Blank) visible en una matriz suele significar una clave externa sin pareja. Revisa las claves antes de culpar a la medida.

Errores comunes

"Una tabla grande es más simple, así que debe ser mejor"

Es más simple de mirar y más difícil de usar. La primera vez que necesites clientes distintos, una segunda fecha o un nombre de producto corregido, la tabla plana empieza a costarte. Separar una vez, al principio, es la versión barata de ese trabajo.

"Una segmentación filtra toda tabla que comparta el nombre de una columna"

Los nombres de columna no significan nada para el motor. Solo las relaciones llevan filtros. Dos tablas con un customer_id y sin relación entre ellas se ignoran, y una segmentación sobre una nunca toca la otra. Si un visual no reacciona a una segmentación, abre Model view y busca la línea.

"Los filtros viajan en ambos sentidos por una relación"

No por defecto. Van del lado 1 al lado muchos. Un filtro sobre products reduce las líneas, no customers, y un filtro sobre order_items no encoge las listas de otras tablas. Esa asimetría es la razón por la que las dimensiones van en el lado 1 y los números en el lado muchos.

Ponte a prueba

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

En el modelo de Harbor & Pine, ¿qué afirmación sobre customers[customer_id] y orders[customer_id] es cierta?

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