Instrucciones para relaciones de varios a varios
Este artículo está dirigido a un modelador de datos que trabaja con Power BI Desktop. Describe tres escenarios diferentes de modelado de varios a varios. También te proporciona orientación sobre cómo diseñar con éxito para ellos en tus modelos.
Nota
En este artículo no se trata una introducción a las relaciones entre modelos. Si no está familiarizado con las relaciones, sus propiedades o cómo configurarlas, se recomienda que primero lea el artículo Relaciones de modelos en Power BI Desktop.
También es importante que tenga conocimientos sobre el diseño de esquemas de estrella. Para más información, vea Descripción de un esquema de estrella e importancia para Power BI.
Hay tres escenarios diferentes de varios a varios. Pueden ocurrir cuando se requiere que:
- Relacionar dos tablas de dimensiones
- Relacionar dos tablas de hechos
- Relacionar tablas de hechos con un nivel de detalle más alto, cuando la tabla de hechos almacena filas con un nivel de detalle más alto que las de la tabla de dimensión
Relación de dimensiones varios a varios
El escenario clásico de muchos a muchos relaciona dos entidades, por ejemplo, los clientes bancarios y las cuentas bancarias. Tenga en cuenta que los clientes pueden tener varias cuentas y las cuentas pueden tener varios clientes. Cuando una cuenta tiene varios clientes, normalmente se denominan titulares de cuentas conjuntas .
El modelado de estas entidades es sencillo. En una tabla de dimensión se almacenan las cuentas y en otra los clientes. Como es característica de las tablas de dimensiones, hay una columna de identificador único (ID) en cada tabla. Para modelar la relación entre las dos tablas, se requiere una tercera tabla. Esta tabla se conoce normalmente como una tabla de interconexión . En este ejemplo, su propósito es almacenar una fila para cada asociación entre cliente y cuenta. Curiosamente, cuando esta tabla solo contiene columnas de identificador, se denomina tabla de hechos sin datos.
Este es un diagrama simplista de las tres tablas de modelo.
La primera tabla se denomina Account
y contiene dos columnas: AccountID
y Account
. La segunda tabla se denomina AccountCustomer
y contiene dos columnas: AccountID
y CustomerID
. La tercera tabla se denomina Customer
y contiene dos columnas: CustomerID
y Customer
. No existen relaciones entre ninguna de las tablas.
Se agregan dos relaciones uno a varios para relacionar las tablas. Este es un diagrama de modelos actualizado de las tablas relacionadas. Se ha agregado una tabla de hechos denominada Transaction
. Registra transacciones de cuenta. Se han ocultado la tabla de puente y todas las columnas de identificador.
Para ayudar a describir cómo funciona la propagación del filtro de relación, el diagrama del modelo se ha modificado para mostrar las filas de la tabla.
Los detalles de las filas de las cuatro tablas se presentan en la siguiente lista en viñetas:
- La tabla
Account
tiene dos filas:AccountID
1 es para Account-01AccountID
2 es para Account-02
- La tabla
Customer
tiene dos filas:CustomerID
91 es para Customer-91CustomerID
92 es para Customer-92
- La tabla
AccountCustomer
tiene tres filas:AccountID
1 está asociado aCustomerID
91AccountID
1 está asociado aCustomerID
92AccountID
2 está asociado aCustomerID
92
- La tabla
Transaction
tiene tres filas:Date
1 de enero de 2019,AccountID
1,Amount
100Date
2 de febrero de 2019,AccountID
2,Amount
200Date
3 de marzo de 2019,AccountID
1,Amount
-25
Veamos lo que sucede cuando se consulta el modelo.
En la imagen siguiente, hay dos objetos visuales de tabla que resumen la columna Amount
de la tabla Transaction
. El primer objeto visual agrupa por cuenta y, por tanto, la suma de las columnas Amount
representa el saldo de cuenta. El segundo objeto visual agrupa por cliente y, por tanto, la suma de las columnas Amount
representa el saldo del cliente.
El primer objeto visual de tabla (Saldo de cuenta) tiene dos columnas: Account
y Amount
. Muestra el resultado siguiente:
- El saldo de Account-01 es 75.
- El saldo de Account-02 es 200.
- El total es 275.
El segundo objeto visual de la tabla (Customer Balance) tiene dos columnas: Customer
y Amount
. Muestra el resultado siguiente:
- El saldo de Customer-91 es 275.
- El saldo de Customer-92 es 275.
- El total es 275.
Un vistazo rápido a las filas de la tabla y el visual del Saldo de Cuenta revela que el resultado es correcto, para cada cuenta y el importe total. Esto se debe a que cada agrupación de cuentas da como resultado una propagación de filtro a la tabla Transaction
de esa cuenta.
Pero parece que algo no es correcto en el objeto visual Customer Balance. Cada cliente en esta visualización tiene el mismo saldo que el saldo total. Este resultado solo podría ser correcto si todos los clientes eran titulares conjuntos de cada cuenta. No es así en este ejemplo. Hay un problema y está relacionado con la propagación de filtros. Los filtros no fluyen hasta la tabla Transaction
.
Si sigue las instrucciones de filtro de relación de la tabla Customer
a la tabla Transaction
, puede determinar que la relación entre las tablas Account
y AccountCustomer
se propaga en dirección incorrecta. La dirección del filtro para esta relación debe establecerse en Both
.
Como se esperaba, no ha habido ningún cambio en el objeto visual Account Balance.
No obstante, el gráfico de Customer Balance ahora muestra el siguiente resultado:
- El saldo de Customer-91 es 75.
- El saldo de Customer-92 es 275.
- El total es 275.
El objeto visual Customer Balance ahora muestra un resultado correcto. Siga las instrucciones del filtro y observe cómo se calcularon los saldos de los clientes. Además, recuerde que el total visual significa todos los clientes.
Alguien que no está familiarizado con las relaciones del modelo podría concluir que el resultado es incorrecto. Pueden preguntar: ¿Por qué no es el saldo total de Customer-91
y Customer-92
igual a 350 (75 + 275)?
La respuesta a su pregunta radica en comprender la relación varios a varios. Cada saldo de cliente puede representar la suma de varios saldos de cuenta, y los saldos del cliente no son aditivos.
Instrucciones para la relación de dimensiones varios a varios
Cuando tenga una relación de varios a varios entre tablas de dimensiones, siga estas instrucciones:
- Agregue cada entidad relacionada de varios a varios como una tabla de modelo, asegurándose de que tiene una columna de identificador.
- Agregue una tabla intermedia para almacenar las entidades asociadas.
- Cree relaciones de uno a varios entre las tres tablas
- Establezca una relación bidireccional para permitir que la propagación de filtros continúe con la tabla de hechos.
- Cuando no sea adecuado tener valores de identificador que faltan, deshabilite la propiedad
Is Nullable
: se producirá un error en la actualización de datos cuando se produzcan valores que faltan. - Oculte la tabla de conexión (a menos que contenga otras columnas o medidas necesarias para la elaboración de informes).
- Oculte las columnas de identificador que no sean adecuadas para los informes (por ejemplo, cuando las columnas almacenan valores de clave suplentes).
- Si tiene sentido dejar visible una columna de identificador, asegúrese de que se encuentra en el lado "uno" de la relación; oculte siempre la columna del lado "varios". Esto se debe a que los filtros aplicados a la diapositiva "uno" dan como resultado un mejor rendimiento del filtro.
- Para evitar confusiones o malinterpretaciones, comunique las explicaciones a los usuarios del informe: puede agregar descripciones con cuadros de texto o información sobre herramientas de encabezado a los objetos visuales.
No se recomienda relacionar directamente las tablas de dimensiones de varios a varios. Este enfoque de diseño requiere configurar una relación con una cardinalidad de varios a varios. Conceptualmente se puede lograr, pero implica que las columnas relacionadas pueden contener valores duplicados. Es una práctica de diseño bien aceptada, sin embargo, que las tablas de dimensiones tienen una columna de ID. Las tablas de dimensiones siempre deben usar la columna ID como el lado "uno" de una relación.
Relación varios a varios de hechos
Un tipo de escenario de varios a varios diferente implica relacionar dos tablas de hechos. Dos tablas de hechos pueden estar relacionadas directamente. Esta técnica de diseño puede ser útil para la exploración rápida y sencilla de datos. Sin embargo, y para ser claro, generalmente no se recomienda este enfoque de diseño. Explicaremos por qué más adelante en esta sección.
Veamos un ejemplo que implica dos tablas de hechos: Order
y Fulfillment
. La tabla Order
contiene una fila por línea de pedido y la tabla de Fulfillment
puede contener cero o más filas por línea de pedido. Las filas de la tabla Order
representan pedidos de ventas. Las filas de la tabla Fulfillment
representan los elementos de pedido que se han enviado. Una relación de varios a varios relaciona las columnas de OrderID
de cada tabla, con propagación de filtros solo de la tabla de Order
(lo que significa que la tabla Order
filtra la tabla Fulfillment
).
La cardinalidad de la relación se establece en Many-to-many
para admitir el almacenamiento de valores de columna duplicados OrderID
en ambas tablas. En la tabla Order
, pueden existir valores de identificador duplicados porque un orden puede tener varias líneas. En la tabla Fulfillment
, pueden existir valores de identificación duplicados porque los pedidos pueden tener varias líneas, y las líneas de pedido pueden ser cumplimentadas por muchos envíos.
A continuación se examinarán las filas de la tabla. En la tabla Fulfillment
, observe que varias líneas de pedido pueden cumplirse con varios envíos. (La ausencia de una línea de pedido significa que el pedido aún no se ha cumplido).
Los detalles de las filas de las dos tablas se describen en la lista de viñetas siguiente:
- La tabla
Order
tiene cinco filas:OrderDate
1 de enero de 2019,OrderID
1,OrderLine
1,ProductID
Prod-A,OrderQuantity
5,Sales
50OrderDate
1 de enero de 2019,OrderID
1,OrderLine
2,ProductID
Prod-B,OrderQuantity
10,Sales
80OrderDate
2 de febrero de 2019,OrderID
2,OrderLine
1,ProductID
Prod-B,OrderQuantity
5,Sales
40OrderDate
2 de febrero de 2019,OrderID
2,OrderLine
2,ProductID
Prod-C,OrderQuantity
1,Sales
20OrderDate
3 de marzo de 2019,OrderID
3,OrderLine
1,ProductID
Prod-C,OrderQuantity
5,Sales
100
- La tabla
Fulfillment
tiene cuatro filas:FulfillmentDate
1 de enero de 2019,FulfillmentID
50,OrderID
1,OrderLine
1,FulfillmentQuantity
2FulfillmentDate
2 de febrero de 2019,FulfillmentID
51,OrderID
2,OrderLine
1,FulfillmentQuantity
5FulfillmentDate
2 de febrero de 2019,FulfillmentID
52,OrderID
1,OrderLine
1,FulfillmentQuantity
3FulfillmentDate
1 de enero de 2019,FulfillmentID
53,OrderID
1,OrderLine
2,FulfillmentQuantity
10
Veamos lo que sucede cuando se consulta el modelo. Aquí tienes una representación visual en tabla que compara las cantidades de pedidos y cumplimiento por la columna OrderID
de la tabla Order
.
El objeto visual presenta un resultado exacto. Sin embargo, la utilidad del modelo está limitada porque solo puede filtrar o agrupar por Order
tabla OrderID
columna.
Instrucciones para la relación de hechos varios a varios
Por lo general, no se recomienda relacionar dos tablas de hechos directamente mediante cardinalidad de varios a varios. La razón principal es que el modelo no proporcionará flexibilidad en las maneras en que los objetos visuales del informe filtran o agrupan. En el ejemplo, solo es posible que los objetos visuales filtren o agrupe por la columna OrderID
de la tabla Order
. Otro motivo se relaciona con la calidad de los datos. Si los datos tienen problemas de integridad, es posible que se omitan algunas filas durante la consulta debido a la cardinalidad de varios hombres y a las relaciones limitadas.
En lugar de relacionar las tablas de hechos directamente, le recomendamos que implemente un diseño de esquema estrella. Esto significa que agrega tablas de dimensiones. A continuación, estas tablas de dimensiones se relacionan con las tablas de hechos mediante relaciones de uno a varios. Este enfoque de diseño es sólido, ya que ofrece de forma eficaz opciones de informes flexibles. Permite filtrar o agrupar mediante cualquiera de las columnas de la tabla de dimensiones y resumir columnas de cualquier tabla de hechos relacionada.
Consideremos una mejor solución.
Observe los siguientes cambios de diseño:
- El modelo ahora tiene cuatro tablas adicionales:
OrderLine
,OrderDate
,Product
yFulfillmentDate
. - Las cuatro tablas adicionales son todas las tablas de dimensiones en las que las relaciones de uno a varios las relacionan con las tablas de hechos.
- La tabla
OrderLine
contiene la columnaOrderLineID
, que almacena el valor deOrderID
multiplicado por 100, además del valor de columnaOrderLine
, un identificador para cada línea de pedido. - Las tablas
Order
yFulfillment
ahora contienen una columna deOrderLineID
y ya no contienen las columnasOrderID
yOrderLine
. - La tabla
Fulfillment
ahora contiene columnasOrderDate
yProductID
. - La tabla
FulfillmentDate
tiene una relación solo con la tablaFulfillment
. - Todas las columnas de identificador están ocultas.
El tiempo necesario para adoptar un diseño de esquema de estrella ofrece las siguientes ventajas:
- Los objetos visuales del informe pueden filtrar o agrupar por cualquier columna visible de las tablas de dimensión.
- Los objetos visuales del informe pueden resumir por cualquier columna visible de las tablas de hechos.
- Los filtros aplicados a las tablas
OrderLine
,OrderDate
oProduct
se aplican también a ambas tablas de hechos. - Todas las relaciones son de uno a varios, y cada una es una relación sólida. Los problemas de integridad de datos no se enmascararán. Para obtener más información sobre la evaluación de relaciones, consulte Relaciones de modelo en Power BI Desktop.
Relación de hechos con un nivel de detalle más alto
Este escenario de varios a varios es muy diferente de los otros dos que ya se describen en este artículo.
Veamos un ejemplo que implica cuatro tablas: Date
, Sales
, Product
y Target
. Las tablas Date
y Product
son tablas de dimensiones y las relaciones de uno a varios conectan cada una con la tabla de hechos Sales
. Hasta ahora, representa un buen diseño de esquema de estrella. Sin embargo, la tabla Target
todavía no está relacionada con las otras tablas.
La tabla Target
contiene tres columnas: Category
, TargetQuantity
y TargetYear
. Las filas de la tabla revelan una granularidad de la categoría de año y producto. En otras palabras, los objetivos, que se usan para medir el desempeño de las ventas, se establecen cada año para cada categoría de producto.
Dado que la tabla Target
almacena datos en un nivel superior a las tablas de dimensiones, no se puede crear una relación uno a varios. Bueno, es cierto para una sola de las relaciones. Vamos a explorar cómo la tabla Target
puede estar relacionada con las tablas de dimensiones.
Relación de períodos de tiempo con un nivel de detalle más alto
Una relación entre las tablas de Date
y Target
debe ser una relación de uno a varios. Esto se debe a que los valores de columna TargetYear
son fechas. En este ejemplo, cada columna TargetYear
almacena la primera fecha del año de destino.
Sugerencia
Cuando se almacenan hechos con una granularidad de tiempo superior al día, establezca el tipo de datos de la columna en Fecha (o Número entero si utiliza claves de fecha). En la columna, almacene un valor que represente el primer día del período de tiempo. Por ejemplo, un período de año se registra como el 1 de enero del año y un período de mes se registra como el primer día de ese mes.
Sin embargo, se debe tener cuidado para asegurarse de que los filtros de nivel de mes o fecha produzcan un resultado significativo. Sin una lógica de cálculo especial, los objetos visuales de informe pueden notificar que las fechas de destino son literalmente el primer día de cada año. Todos los demás días (y todos los meses excepto enero) resumirán la cantidad de destino como en blanco.
En la siguiente visualización de matriz se muestra lo que sucede cuando el usuario del informe desglosa un año en sus meses. El objeto visual resume la columna TargetQuantity
. (La opción Mostrar elementos sin datos se ha habilitado para las filas de matriz).
Para evitar este comportamiento, se recomienda controlar el resumen de los datos de hechos mediante medidas. Una manera de controlar el resumen es devolver BLANK cuando se consultan períodos de tiempo de nivel inferior. Otra manera, definida con algunos DAX sofisticados, es distribuir valores en períodos de tiempo de menor nivel.
Considere la siguiente definición de medida que usa la función DAX ISFILTERED. Solo devuelve un valor cuando no se filtran las columnas Date
y Month
.
Target Quantity =
IF(
NOT ISFILTERED('Date'[Date])
&& NOT ISFILTERED('Date'[Month]),
SUM(Target[TargetQuantity])
)
El siguiente objeto visual de matriz usa la medida Target Quantity
. Muestra que todas las cantidades de destino mensuales están en blanco.
Relación con un nivel de detalle más alto (distinto de fechas)
Al relacionar una columna que no sea de fecha de una tabla de dimensión con una tabla de hechos (y en un nivel de detalle más alto que la tabla de dimensión) se requiere otro enfoque de diseño.
Las columnas Category
(de las tablas Product
y Target
) contienen valores duplicados. Por lo tanto, no hay "un" lado para una relación de uno a varios. En este caso, tendrá que crear una relación de varios a varios. La relación debe propagar filtros en una sola dirección, desde la tabla de dimensiones hasta la tabla de hechos.
A continuación se examinarán las filas de la tabla.
En la tabla Target
, hay cuatro filas: dos filas para cada año objetivo (2019 y 2020) y dos categorías (Ropa y Accesorios). En la tabla Product
, hay tres productos. Dos pertenecen a la categoría de ropa, y una pertenece a la categoría de accesorios. Uno de los colores de la ropa es verde, y los dos restantes son azules.
Una tabla visual agrupada por la columna Category
de la tabla Product
genera el siguiente resultado. Sin embargo, esta visualización genera el resultado correcto. Ahora vamos a considerar lo que sucede cuando la columna Color
de la tabla Product
se usa para agrupar la cantidad objetivo.
El objeto visual genera una representación incorrecta de los datos. ¿Qué está pasando aquí?
Un filtro de la columna Color
de la tabla Product
da como resultado dos filas. Una de las filas es para la categoría Ropa, y la otra es para la categoría Accesorios. Estos dos valores de categoría se propagan como filtros a la tabla Target
. En otras palabras, como los productos de dos categorías usan el color azul, esas categorías se usan para filtrar los destinos.
Para evitar este comportamiento, como se ha descrito anteriormente, se recomienda controlar el resumen de los datos de hechos mediante medidas.
Tenga en cuenta la siguiente definición de medida. Tenga en cuenta que todas las columnas de la tabla Product
que están debajo del nivel de categoría son evaluadas teniendo en cuenta los filtros.
Target Quantity =
IF(
NOT ISFILTERED('Product'[ProductID])
&& NOT ISFILTERED('Product'[Product])
&& NOT ISFILTERED('Product'[Color]),
SUM(Target[TargetQuantity])
)
El siguiente objeto visual de tabla se usa la medida Target Quantity
. Muestra que todas las cantidades de destino de color están en blanco.
El diseño final del modelo es similar al siguiente.
Instrucciones para la relación de hechos con un nivel de detalle más alto
Cuando necesite relacionar una tabla de dimensiones con una tabla de hechos y la tabla de hechos almacena filas en un nivel más alto que las filas de la tabla de dimensiones, siga estas instrucciones:
- Para fechas de hechos con un nivel de detalle más alto
- En la tabla de hechos, almacene la primera fecha del período de tiempo.
- Cree una relación de uno a varios entre la tabla de fechas y la de hechos.
- Para otros hechos con un nivel de detalle más alto
- Cree una relación de varios a varios entre la tabla de dimensiones y la tabla de hechos.
- Para ambos tipos
- Resumen de controles con lógica de medida: devuelve BLANK cuando se usan columnas de dimensión de nivel inferior para filtrar o agrupar.
- Ocultar columnas resumibles en la tabla de hechos, lo que garantiza que solo se puedan usar métricas para resumir la tabla de hechos.
Contenido relacionado
Para obtener más información relacionada con este artículo, consulte los siguientes recursos: