Many-to-Many Relationship di Power BI: Panduan Lengkap dari Konsep, Bridge Table hingga Best Practice
Relationship merupakan jantung dari semantic model Power BI. Ketika relationship dirancang dengan benar, filter dapat mengalir secara logis dari dimension menuju fact table, DAX menjadi lebih sederhana, visual memberikan hasil yang dapat diprediksi, dan model lebih mudah digunakan oleh report developer maupun pengguna bisnis.
Namun tidak semua hubungan bisnis dapat direpresentasikan dengan pola sederhana one-to-many (1:*).
Dalam banyak kasus nyata, satu entitas dapat berhubungan dengan banyak entitas lain, sementara entitas kedua tersebut juga dapat berhubungan kembali dengan banyak entitas pertama.
Contohnya:
Seorang customer dapat memiliki beberapa rekening bank.
Satu rekening bank juga dapat dimiliki oleh beberapa customer.
Seorang mahasiswa dapat mengikuti beberapa mata kuliah.
Satu mata kuliah dapat diikuti oleh banyak mahasiswa.
Seorang sales representative dapat menangani beberapa wilayah.
Satu wilayah dapat ditangani oleh lebih dari satu sales representative.
Seorang dokter dapat menangani banyak pasien.
Seorang pasien dapat ditangani oleh beberapa dokter.
Inilah contoh hubungan bisnis yang disebut many-to-many.
Di Power BI, many-to-many merupakan salah satu topik data modeling yang paling penting sekaligus paling sering disalahpahami.
Kesalahan paling umum adalah menganggap bahwa setiap hubungan bisnis many-to-many harus langsung dibuat sebagai relationship:
* ↔ *
Padahal tidak selalu demikian.
Microsoft justru merekomendasikan penggunaan bridging table ketika menghubungkan dua dimension table dalam hubungan many-to-many. Dalam pola tersebut, relationship fisik pada semantic model justru berupa relationship one-to-many, bukan direct many-to-many.
Karena itu, memahami many-to-many bukan hanya memahami tombol Cardinality = Many-to-many.
Kita perlu memahami:
business relationship;
grain;
bridge table;
factless fact table;
filter propagation;
bidirectional filtering;
limited relationship;
fact-to-fact relationship;
higher-grain fact;
non-additive values;
dan bagaimana star schema seharusnya dirancang.
Apa Itu Many-to-Many Relationship?
Secara konseptual, many-to-many relationship adalah hubungan ketika satu record atau entitas pada sisi pertama dapat berhubungan dengan banyak record di sisi kedua, dan satu record pada sisi kedua juga dapat berhubungan dengan banyak record di sisi pertama.
Notasinya:
* : *
atau:
Many ↔ Many
Namun kita perlu membedakan dua istilah:
Many-to-many business relationship
dan:
Many-to-many cardinality pada Power BI.
Kedua konsep tersebut berkaitan, tetapi tidak selalu sama.
Hubungan bisnis many-to-many sering kali justru lebih baik dimodelkan menggunakan bridge table dengan beberapa relationship 1:*.
Contoh Sederhana Many-to-Many
Bayangkan sebuah bank memiliki dua customer:
| CustomerID | Customer |
|---|---|
| 91 | Customer-91 |
| 92 | Customer-92 |
Kemudian terdapat dua rekening:
| AccountID | Account |
|---|---|
| 1 | Account-01 |
| 2 | Account-02 |
Hubungan bisnisnya:
Customer-91 memiliki Account-01.
Customer-92 memiliki Account-01 dan Account-02.
Account-01 dimiliki oleh Customer-91 dan Customer-92.
Account-02 dimiliki oleh Customer-92.
Berarti:
Customer dapat memiliki banyak Account.
Account dapat dimiliki banyak Customer.
Secara bisnis:
Customer * ↔ * Account
Microsoft menggunakan skenario customer dan bank account ini sebagai contoh klasik relationship many-to-many antar dimension.
Mengapa Kita Tidak Langsung Menghubungkan Customer dan Account?
Misalkan Customer mempunyai CustomerID unik.
Account juga memiliki AccountID unik.
Tidak terdapat satu kolom yang secara langsung dapat menyatakan seluruh kombinasi ownership.
Kita membutuhkan tabel yang menjawab pertanyaan:
Customer mana mempunyai Account mana?
Karena itu kita membuat tabel ketiga.
Misalnya:
AccountCustomer
| CustomerID | AccountID |
|---|---|
| 91 | 1 |
| 92 | 1 |
| 92 | 2 |
Tabel tersebut menyimpan satu baris untuk setiap hubungan Customer–Account.
Inilah yang disebut:
Bridge Table
atau:
Bridging Table.
Apa Itu Bridge Table?
Bridge table merupakan tabel perantara yang menyimpan association atau hubungan antara dua entitas yang mempunyai hubungan many-to-many.
Strukturnya biasanya sangat sederhana.
Dalam contoh sebelumnya:
| CustomerID | AccountID |
|---|---|
| 91 | 1 |
| 92 | 1 |
| 92 | 2 |
Bridge table tidak harus mempunyai measure.
Fungsi utamanya adalah menyatakan association.
Microsoft menjelaskan bahwa ketika bridge table hanya berisi identifier atau dimension keys dan tidak mempunyai measure, tabel tersebut disebut factless fact table.
Apa Itu Factless Fact Table?
Fact table biasanya kita bayangkan berisi angka seperti:
Sales Amount;
Quantity;
Cost;
Profit;
Discount;
atau Inventory.
Namun sebuah fact table tidak selalu harus mempunyai numeric measure.
Factless fact table hanya merekam bahwa suatu kejadian atau association terjadi.
Contohnya:
Customer 91 terkait dengan Account 1.
Customer 92 terkait dengan Account 1.
Customer 92 terkait dengan Account 2.
Informasi pentingnya bukan nilai numerik, tetapi keberadaan relationship tersebut.
Karena itu AccountCustomer dapat dipandang sebagai factless fact table.
Model Many-to-Many yang Direkomendasikan
Daripada:
Customer * ↔ * Account
secara langsung, buat:
Customer 1 → * AccountCustomer
dan:
Account 1 → * AccountCustomer
Secara business relationship tetap many-to-many.
Tetapi pada semantic model, masing-masing dimension mempunyai unique key pada sisi “1”, sedangkan bridge menyimpan duplicate keys pada sisi “*”.
Microsoft merekomendasikan pola ini ketika menghubungkan dua dimension yang memiliki relationship many-to-many.
Perbedaan Business Many-to-Many dan Cardinality *:*
Ini adalah konsep yang sangat penting.
Misalkan relationship bisnis:
Customer ↔ Account
adalah many-to-many.
Tetapi physical relationship dalam model dapat menjadi:
Customer:
1 → *
AccountCustomer
dan:
Account:
1 → *
AccountCustomer.
Artinya:
Hubungan bisnis many-to-many tidak selalu membutuhkan cardinality *:* secara langsung.
Ini merupakan salah satu prinsip terpenting dalam Power BI data modeling.
Mengapa Microsoft Tidak Merekomendasikan Direct Many-to-Many antar Dimension?
Microsoft tidak merekomendasikan menghubungkan dua dimension table secara langsung menggunakan many-to-many cardinality.
Alasannya adalah dimension table secara desain seharusnya memiliki identifier unik yang dapat menjadi sisi “one” relationship.
Menggunakan bridge table mempertahankan prinsip tersebut dan menghasilkan model yang lebih eksplisit serta lebih mudah dipahami.
Contoh:
DimCustomer mempunyai CustomerID unik.
DimAccount mempunyai AccountID unik.
BridgeAccountCustomer menyimpan hubungan keduanya.
Ini lebih baik dibanding mencoba membuat column relationship langsung dengan duplicate values pada kedua dimension.
Bagaimana Filter Mengalir pada Bridge Table?
Ini bagian yang sangat penting.
Misalnya model mempunyai:
Customer → AccountCustomer ← Account → Transaction
Transaction menyimpan transaksi rekening.
Kita ingin memilih Customer pada slicer dan melihat transaksi dari account yang dimilikinya.
Filter harus bergerak:
Customer
↓
AccountCustomer
↓
Account
↓
Transaction
Masalahnya, relationship default antara Account dan AccountCustomer biasanya memfilter dari Account menuju bridge.
Untuk memungkinkan filter bergerak dari bridge kembali menuju Account, salah satu relationship perlu mempunyai arah filter Both.
Dalam contoh Microsoft, relationship antara Account dan AccountCustomer diatur menjadi bidirectional sehingga filter dari Customer dapat terus diteruskan hingga Transaction.
Apakah Berarti Semua Relationship Harus Both?
Tidak.
Ini merupakan kesalahan yang berbahaya.
Jangan mengubah seluruh relationship menjadi Both hanya karena sebuah visual tidak bekerja.
Microsoft secara umum menyarankan penggunaan bidirectional filtering secara selektif karena filter dua arah dapat menambah kompleksitas dan membuka kemungkinan munculnya multiple filter paths atau ambiguity.
Untuk model bridge table, biasanya hanya relationship yang memang diperlukan untuk meneruskan filter lintas bridge yang dibuat bidirectional.
Prinsipnya:
Gunakan Both karena kebutuhan filter propagation yang jelas, bukan sebagai solusi universal.
Contoh Filter Propagation Customer ke Transaction
Bayangkan struktur berikut:
Customer
CustomerID 91
CustomerID 92
Bridge AccountCustomer
91 → Account 1
92 → Account 1
92 → Account 2
Transaction
| AccountID | Amount |
|---|---|
| 1 | 100 |
| 2 | 200 |
| 1 | -25 |
Balance Account 1:
100 – 25 = 75
Balance Account 2:
200
Customer 91 hanya mempunyai Account 1.
Maka:
Customer 91 Balance = 75
Customer 92 mempunyai Account 1 dan Account 2.
Maka:
Customer 92 Balance = 75 + 200 = 275
Mengapa Grand Total Bukan 350?
Ini salah satu konsep paling menarik dalam many-to-many.
Customer 91 = 75.
Customer 92 = 275.
Jika dijumlahkan:
75 + 275 = 350.
Tetapi total seluruh account sebenarnya hanya:
75 + 200 = 275.
Mengapa Power BI menampilkan grand total 275, bukan 350?
Karena Account 1 dimiliki oleh Customer 91 dan Customer 92.
Saldo Account 1 tidak boleh dihitung dua kali ketika menghitung total seluruh account.
Microsoft menjelaskan bahwa customer balances dalam skenario ini bersifat non-additive. Nilai per customer tidak dapat begitu saja dijumlahkan untuk mendapatkan grand total karena shared account dapat muncul dalam lebih dari satu customer context.
Apa Itu Non-Additive Measure?
Additive measure merupakan angka yang dapat dijumlahkan secara aman di seluruh dimension.
Contohnya jumlah unit barang terjual sering kali additive.
Tetapi beberapa ukuran tidak dapat dijumlahkan begitu saja.
Dalam contoh joint account:
Customer 91 mencakup Account 1.
Customer 92 juga mencakup Account 1.
Jika saldo customer dijumlahkan, Account 1 dihitung dua kali.
Karena itu total harus dihitung ulang berdasarkan filter context keseluruhan, bukan sekadar menjumlahkan displayed rows.
Konsep seperti ini penting saat menjelaskan kepada pengguna mengapa:
Grand Total Power BI tidak selalu sama dengan penjumlahan manual seluruh row yang terlihat.
Best Practice Bridge Table Menurut Microsoft
Untuk relationship many-to-many antar dimension, Microsoft memberikan beberapa panduan utama. Setiap entity sebaiknya memiliki dimension table dengan ID unik, bridge table digunakan untuk menyimpan association antar entity, lalu relationship 1:* dibangun menuju bridge. Salah satu relationship dapat dibuat bidirectional jika dibutuhkan agar filter dapat terus bergerak menuju fact table. Bridge table dan technical ID yang tidak diperlukan untuk reporting umumnya disembunyikan dari report author.
Tujuan akhirnya bukan sekadar membuat relationship bekerja, melainkan membuat semantic model tetap intuitif.
Mengapa Bridge Table Sebaiknya Disembunyikan?
Bridge table biasanya merupakan implementation detail.
Report author seharusnya bekerja dengan:
Customer;
Account;
Transaction;
bukan:
CustomerID dari Bridge;
AccountID dari Bridge;
atau technical surrogate keys.
Jika bridge hanya digunakan untuk relationship, menyembunyikannya membuat Data pane jauh lebih bersih.
Microsoft juga merekomendasikan menyembunyikan bridge table jika tabel tersebut tidak mempunyai field atau measure yang memang dibutuhkan untuk reporting.
Sembunyikan Key di Sisi Many
Misalnya:
Customer[CustomerID]
terhubung dengan:
Bridge[CustomerID].
Jika CustomerID memang diperlukan pada report, lebih baik expose key dari sisi dimension atau sisi “one”.
Technical key pada sisi many biasanya sebaiknya disembunyikan.
Microsoft menyebut bahwa filter yang diterapkan pada sisi “one” mempunyai karakteristik filter yang lebih baik dibanding menggunakan key dari sisi many.
Skenario Many-to-Many Kedua: Fact-to-Fact
Selain hubungan antar dimension, many-to-many juga dapat muncul ketika dua fact table ingin dihubungkan.
Microsoft memberikan contoh:
Order
dan:
Fulfillment.
Order menyimpan order line.
Fulfillment menyimpan shipment atau pemenuhan order.
Satu order dapat mempunyai beberapa order line.
Satu order line juga dapat dikirim melalui beberapa fulfillment.
Karena itu OrderID dapat duplicate pada kedua tabel.
Contoh Fact Order
| OrderID | OrderLine | ProductID | OrderQty |
|---|---|---|---|
| 1001 | 1 | P001 | 10 |
| 1001 | 2 | P002 | 5 |
| 1002 | 1 | P003 | 8 |
OrderID 1001 duplicate karena mempunyai dua order line.
Contoh Fact Fulfillment
| FulfillmentID | OrderID | OrderLine | ShipQty |
|---|---|---|---|
| F001 | 1001 | 1 | 4 |
| F002 | 1001 | 1 | 6 |
| F003 | 1001 | 2 | 5 |
OrderID 1001 juga duplicate.
Jika kita menghubungkan:
Order[OrderID]
dengan:
Fulfillment[OrderID]
kedua sisi mempunyai duplicate.
Cardinality-nya:
* : *
Apakah Direct Fact-to-Fact Many-to-Many Direkomendasikan?
Secara teknis bisa.
Microsoft bahkan menyebut direct relationship antara dua fact table dapat berguna untuk eksplorasi data yang cepat dan sederhana.
Namun Microsoft secara umum tidak merekomendasikan desain ini sebagai model akhir.
Mengapa?
Karena kemampuan reporting menjadi terbatas.
Filter dan grouping cenderung bergantung pada field yang terdapat dalam salah satu fact table.
Selain itu, relationship many-to-many dievaluasi sebagai limited relationship sehingga masalah data integrity dapat menghasilkan row yang tidak muncul dalam query result.
Solusi Lebih Baik untuk Fact-to-Fact: Star Schema
Daripada:
FactOrder * ↔ * FactFulfillment
Microsoft merekomendasikan menambahkan dimension bersama.
Contohnya:
DimOrderLine
DimOrderDate
DimProduct
DimFulfillmentDate
Kemudian:
DimOrderLine 1 → * FactOrder
DimOrderLine 1 → * FactFulfillment
DimProduct 1 → * FactOrder
DimProduct 1 → * FactFulfillment
dan seterusnya.
Dengan demikian kedua fact table tidak perlu dihubungkan langsung.
Mengapa Shared Dimension Lebih Baik?
Misalnya DimProduct memfilter:
FactOrder
dan:
FactFulfillment.
Pengguna dapat memilih Product dan kemudian melihat:
Order Quantity;
Fulfilled Quantity;
Outstanding Quantity;
Fulfillment Rate;
dalam satu filter context yang konsisten.
Microsoft menjelaskan bahwa desain star schema seperti ini membuat report dapat melakukan filter atau grouping menggunakan dimension dan melakukan summarization pada fact table yang terkait, sekaligus mempertahankan regular one-to-many relationships.
Gunakan OrderLineID untuk Menyamakan Grain
Salah satu improvement yang dijelaskan Microsoft adalah membangun key pada grain order line.
Misalnya:
OrderID = 1001
OrderLine = 2
Dibuat identifier:
OrderLineID
Yang penting bukan format persisnya, tetapi bahwa OrderLineID mengidentifikasi satu order line secara unik.
Dimension OrderLine kemudian dapat menjadi common dimension bagi FactOrder dan FactFulfillment.
Grain Sekali Lagi Menjadi Kunci
Dalam artikel One-to-One sebelumnya kita membahas grain.
Pada many-to-many, grain bahkan lebih penting.
Tanyakan:
Satu row dalam tabel ini mewakili apa?
FactOrder mungkin:
one row per order line.
FactFulfillment mungkin:
one row per shipment per order line.
Karena grain berbeda, OrderID saja tidak cukup untuk menyatakan association secara presisi.
Memahami grain membantu menemukan dimension atau key yang tepat.
Many-to-Many Cardinality adalah Limited Relationship
Ini salah satu konsep advanced yang wajib dipahami.
Microsoft mengklasifikasikan relationship berdasarkan evaluasinya menjadi:
Regular relationship
dan:
Limited relationship.
Relationship yang menggunakan many-to-many cardinality merupakan limited relationship karena tidak ada guaranteed “one” side.
Apa Konsekuensi Limited Relationship?
Pada limited relationship, Power BI tidak melakukan table expansion dengan cara yang sama seperti regular relationship.
Untuk Import model, join limited relationship diselesaikan ketika query dijalankan.
Microsoft menjelaskan bahwa limited relationship menggunakan semantik yang setara dengan INNER JOIN, sehingga blank virtual row tidak ditambahkan untuk mengompensasi pelanggaran referential integrity.
Implikasinya:
unmatched records dapat tidak muncul seperti yang mungkin Anda harapkan dari regular relationship.
Inilah salah satu alasan mengapa data integrity penting dalam direct many-to-many relationship.
RELATED dan Limited Relationship
Limited relationship juga mempunyai beberapa pembatasan DAX.
Microsoft menjelaskan bahwa fungsi RELATED tidak dapat digunakan melalui limited relationship untuk mengambil nilai dari sisi yang dianggap “one”.
Ini semakin menegaskan bahwa relationship *:* tidak boleh diperlakukan seolah-olah sama dengan relationship 1:* biasa.
Skenario Many-to-Many Ketiga: Higher-Grain Fact
Skenario ketiga sering terjadi dalam dunia bisnis.
Misalnya kita mempunyai:
DimProduct pada level Product.
FactSales pada level transaction/product.
Tetapi FactTarget hanya tersedia pada level Product Category.
Contoh:
| Year | Category | TargetQuantity |
|---|---|---|
| 2026 | Hair Care | 500000 |
| 2026 | Personal Care | 400000 |
Sementara DimProduct:
| ProductID | Product | Category |
|---|---|---|
| P001 | Shampoo A | Hair Care |
| P002 | Shampoo B | Hair Care |
| P003 | Soap A | Personal Care |
Target berada pada:
Category grain.
Product berada pada:
Product grain.
FactTarget berarti mempunyai grain yang lebih tinggi atau lebih aggregated dibandingkan DimProduct.
Microsoft mengidentifikasi skenario ini sebagai salah satu penggunaan many-to-many relationship yang valid.
Mengapa Tidak Bisa Menggunakan 1:*?
DimProduct[Category] berisi:
Hair Care
Hair Care
Personal Care
Category duplicate karena ada banyak produk dalam satu category.
FactTarget[Category] juga berulang dari tahun ke tahun.
Misalnya:
Hair Care 2025
Hair Care 2026
Personal Care 2025
Personal Care 2026
Kedua sisi mempunyai duplicate.
Maka relationship berdasarkan Category menjadi:
* → *
Microsoft menyarankan filter berjalan satu arah dari dimension menuju higher-grain fact dalam skenario ini.
Bahaya Higher-Grain Fact
Masalah muncul ketika pengguna mencoba menganalisis Target pada grain yang lebih rendah daripada grain target sebenarnya.
Misalnya Target ditetapkan berdasarkan Category.
Tetapi report mencoba menampilkan:
Target per Product;
Target per Color;
Target per SKU.
Pertanyaan penting:
Bagaimana target category harus dialokasikan kepada masing-masing product?
Jika business tidak memberikan allocation rule, Power BI tidak bisa secara ajaib menentukan jawabannya.
Contoh Misrepresentation
Misalnya Hair Care target = 100.
Hair Care mempunyai:
Shampoo A
Shampoo B.
Jika report menampilkan Product:
Shampoo A = 100
Shampoo B = 100
pengguna bisa salah menganggap total Hair Care = 200.
Padahal sebenarnya target category hanya 100.
Ini bukan sekadar masalah DAX.
Ini adalah masalah grain mismatch.
Measure Harus Mengontrol Summarization
Microsoft menyarankan agar higher-grain fact tidak dibiarkan diringkas secara sembarangan melalui implicit aggregation.
Gunakan explicit measure untuk memastikan nilai hanya muncul pada level yang mempunyai makna bisnis.
Contoh pendekatan:
Target Quantity Safe =
VAR IsBelowCategory =
ISINSCOPE(DimProduct[Product])
|| ISINSCOPE(DimProduct[ProductID])
|| ISINSCOPE(DimProduct[Color])
RETURN
IF(
IsBelowCategory,
BLANK(),
SUM(FactTarget[TargetQuantity])
)
Dengan pendekatan tersebut:
Target pada Category → tampil.
Target pada level Product → BLANK.
Target pada level Color → BLANK.
Ini lebih baik daripada menampilkan angka yang sebenarnya tidak memiliki makna bisnis.
Mengapa BLANK Justru Bisa Menjadi Jawaban yang Benar?
Dalam dashboard, pengguna sering menganggap BLANK berarti error.
Tidak selalu.
Jika target hanya ditetapkan pada level Category, maka pertanyaan:
Berapa target Product A?
mungkin memang tidak mempunyai jawaban.
Menampilkan BLANK lebih jujur daripada menampilkan target Category seolah-olah itu target Product.
Microsoft secara eksplisit merekomendasikan mengembalikan BLANK ketika lower-level dimension digunakan untuk memfilter atau grouping higher-grain facts.
Higher-Grain Fact dan Date
Kasus time dimension sedikit berbeda.
Misalnya target tersedia per tahun.
DimDate tersedia per hari.
Microsoft menyarankan higher-grain fact date menyimpan tanggal pertama dari periodenya.
Contoh:
Target 2026 → 1 Januari 2026.
Target September 2026 → 1 September 2026.
Kemudian Date dimension tetap dapat mempunyai relationship 1:* menuju FactTarget.
Masalah Drill Down Year ke Month
Namun relationship saja tidak cukup.
Misalnya annual target 1.200 unit disimpan pada:
1 Januari 2026.
Ketika pengguna drill down dari Year ke Month, target mungkin hanya muncul pada Januari sedangkan Februari sampai Desember BLANK.
Secara relationship itu benar.
Secara business reporting, mungkin membingungkan.
Microsoft menyarankan controlling summarization dengan measure atau menggunakan DAX allocation logic apabila memang ada aturan bisnis untuk mendistribusikan annual target ke month.
Jangan Membuat Allocation Rule Tanpa Dasar Bisnis
Misalnya annual target:
12.000 unit.
Membaginya otomatis menjadi:
1.000 per bulan
belum tentu benar.
Mungkin bisnis mempunyai seasonality:
Januari = 8%
Februari = 7%
Ramadan = 15%
dan seterusnya.
Allocation rule harus berasal dari business logic, bukan hanya kebutuhan visualisasi.
Three Many-to-Many Scenarios Menurut Microsoft
Dengan demikian Microsoft membedakan tiga situasi penting. Pertama, relationship many-to-many antar dimension, yang sebaiknya dimodelkan menggunakan bridge table. Kedua, hubungan antar fact table, yang secara teknis dapat dibuat langsung tetapi biasanya lebih baik dirombak menjadi star schema dengan shared dimensions. Ketiga, higher-grain fact, ketika fact table menyimpan data pada grain yang lebih tinggi daripada dimension yang menghubungkannya.
Many-to-Many dan Star Schema
Star schema tetap menjadi fondasi penting.
Dalam star schema:
Dimension digunakan untuk filtering dan grouping.
Fact digunakan untuk summarization.
Sisi “1” pada 1:* umumnya merupakan dimension.
Sisi “*” umumnya merupakan fact.
Microsoft menjelaskan bahwa relationship dan cardinality membantu menentukan peran dimension dan fact dalam semantic model.
Bridge Table Tidak Merusak Star Schema
Beberapa pengguna merasa bridge table membuat star schema menjadi “tidak murni”.
Itu tidak menjadi masalah.
Real-world business model memang kadang membutuhkan factless fact atau bridge.
Yang penting:
grain jelas;
relationship jelas;
filter path jelas;
dan report author memahami model.
Microsoft bahkan menyebut bridge/factless fact sebagai best-practice approach untuk many-to-many antar dimension.
Contoh Many-to-Many pada Sales Organization
Misalnya satu salesman dapat menangani banyak territory.
Satu territory juga dapat ditangani beberapa salesman.
DimSalesperson:
| SalespersonID | Salesperson |
|---|---|
| S01 | Andi |
| S02 | Budi |
DimTerritory:
| TerritoryID | Territory |
|---|---|
| T01 | Jakarta Selatan |
| T02 | Jakarta Barat |
BridgeSalespersonTerritory:
| SalespersonID | TerritoryID |
|---|---|
| S01 | T01 |
| S01 | T02 |
| S02 | T02 |
Secara bisnis:
Salesperson * ↔ * Territory.
Secara semantic model:
DimSalesperson 1 → * Bridge
DimTerritory 1 → * Bridge.
Contoh Many-to-Many pada Pendidikan
Student dapat mengikuti banyak Course.
Course mempunyai banyak Student.
Buat:
DimStudent
DimCourse
BridgeEnrollment.
BridgeEnrollment dapat mempunyai:
StudentID
CourseID
EnrollmentDate
Status.
Jika bridge mempunyai additional business attributes seperti EnrollmentDate, tabel tersebut bahkan menjadi lebih dari sekadar technical bridge.
Contoh Many-to-Many pada Healthcare
Patient dapat memiliki banyak Doctor.
Doctor menangani banyak Patient.
Buat:
DimPatient
DimDoctor
BridgeDoctorPatient.
Jika hubungan mempunyai periode berlaku, bridge dapat juga mempunyai:
StartDate;
EndDate;
Role;
PrimaryDoctorFlag.
Ini menunjukkan bahwa many-to-many modeling tidak hanya persoalan cardinality, tetapi juga representasi business relationship.
Contoh Many-to-Many pada Produk dan Promosi
Satu product dapat masuk beberapa promotion.
Satu promotion dapat berlaku untuk banyak product.
Model:
DimProduct
DimPromotion
BridgeProductPromotion.
Dengan relationship yang dirancang dengan benar, report dapat menjawab:
produk apa yang mengikuti Promotion A;
berapa sales dari product yang termasuk Promotion A;
promotion apa saja yang pernah berlaku pada Product X.
Jangan Gunakan Direct *:* Hanya Karena Power BI Mengizinkannya
Ini serupa dengan pelajaran pada one-to-one relationship.
Power BI menyediakan cardinality:
Many-to-many (*:*)
tetapi keberadaan fitur bukan berarti fitur tersebut harus menjadi pilihan default.
Microsoft menyebut many-to-many cardinality relatif jarang digunakan dan biasanya ditujukan untuk kebutuhan model yang lebih kompleks, termasuk higher-grain fact atau many-to-many fact scenarios.
Kesalahan Umum 1: Langsung Memilih Many-to-Many Saat Duplicate Muncul
Misalnya Anda mencoba membuat:
DimProduct[ProductID]
→ FactSales[ProductID]
tetapi Power BI mengatakan ProductID pada DimProduct duplicate.
Jangan langsung mengubah cardinality menjadi *:*.
Tanyakan:
Mengapa ProductID duplicate di DimProduct?
Mungkin DimProduct sebenarnya mengandung:
historical versions;
multiple warehouses;
multiple price periods;
duplicate source data;
atau grain yang salah.
Many-to-many tidak boleh menjadi plester untuk data quality issue.
Kesalahan Umum 2: Menghilangkan Duplicate Secara Sembarangan
Kebalikan dari kesalahan pertama juga berbahaya.
Developer menggunakan Remove Duplicates hanya agar relationship menjadi 1:*.
Jika duplicate merepresentasikan association yang valid, Anda telah menghapus informasi bisnis.
Contohnya pada bridge:
S01 → T01
S01 → T02.
Salesperson S01 memang harus muncul dua kali karena ia menangani dua territory.
Kesalahan Umum 3: Mengaktifkan Both di Semua Relationship
Ini sering dilakukan karena:
Kalau Both, filter pasti jalan.
Namun semakin banyak bidirectional relationship, semakin besar kemungkinan model mempunyai beberapa jalur filter menuju tabel yang sama.
Power BI mempunyai mekanisme untuk menyelesaikan relationship path ambiguity, tetapi desain yang jelas jauh lebih baik daripada bergantung pada resolusi ambiguity engine. Microsoft mendokumentasikan bahwa bidirectional relationships dapat memperkenalkan multiple filter propagation paths.
Kesalahan Umum 4: Mengabaikan Grand Total
Pada many-to-many, grand total dapat berbeda dari penjumlahan displayed rows karena association overlap.
Jangan langsung menganggap Power BI salah.
Pahami terlebih dahulu:
grain;
filter context;
shared entities;
dan apakah measure bersifat additive atau non-additive.
Kesalahan Umum 5: Menghubungkan Fact Table Secara Langsung
FactSales * ↔ * FactTarget
atau:
FactOrder * ↔ * FactShipment
mungkin bekerja untuk exploratory report.
Tetapi untuk enterprise semantic model, shared dimensions biasanya menghasilkan architecture yang lebih kuat dan fleksibel.
Microsoft secara eksplisit merekomendasikan star schema daripada direct many-to-many fact-to-fact relationships pada skenario Order/Fulfillment.
Kesalahan Umum 6: Mengabaikan Higher-Grain Facts
Target Category tidak sama dengan Target Product.
Budget Region tidak sama dengan Budget Store.
Annual Target tidak sama dengan Monthly Target.
National Forecast tidak sama dengan Outlet Forecast.
Jangan membiarkan report melakukan drill-down ke level yang lebih rendah seolah-olah angka tersebut memang tersedia pada grain tersebut.
Contoh Kasus FMCG: Target Category vs Sales SKU
Misalnya tim Sales mempunyai actual data pada level:
Date × Outlet × SKU.
Namun annual target diberikan oleh management pada level:
Year × Category.
FactSales grain:
one row per transaction/outlet/SKU.
FactTarget grain:
one row per year/category.
Memaksa target ke level SKU tanpa allocation rule akan menghasilkan interpretasi yang salah.
Solusi:
hubungkan target pada grain yang relevan;
gunakan explicit measure;
return BLANK ketika report berada di bawah grain target;
atau implementasikan allocation jika organisasi mempunyai allocation methodology.
Contoh Kasus Budget vs Actual
Actual expense mungkin tersedia per:
Date;
Department;
Account;
Cost Center.
Sementara Budget hanya tersedia per:
Month;
Department.
Jika pengguna melihat Budget berdasarkan individual Cost Center, nilainya mungkin tidak mempunyai business meaning.
Masalah ini sangat mirip dengan higher-grain target.
Many-to-Many dan DAX
Many-to-many relationship bukan berarti seluruh masalah harus diselesaikan dengan DAX.
Prinsip yang tetap berlaku adalah:
Perbaiki model terlebih dahulu, baru tulis DAX.
DAX seharusnya mengimplementasikan business calculation.
DAX tidak seharusnya menjadi alat untuk menyembunyikan relationship architecture yang tidak jelas.
TREATAS sebagai Virtual Relationship
Dalam skenario advanced, DAX menyediakan fungsi seperti TREATAS untuk menerapkan hasil table expression sebagai filter pada kolom dari tabel lain.
Microsoft menyebut TREATAS berguna pada skenario advanced ketika developer ingin menciptakan virtual relationship selama evaluation suatu calculation.
Namun TREATAS bukan pengganti otomatis bridge table atau star schema.
Gunakan ketika ada alasan calculation-specific yang jelas.
Physical Relationship vs Virtual Relationship
Physical relationship dibuat di Model View.
Keuntungannya:
berlaku untuk keseluruhan semantic model;
lebih mudah dilihat;
lebih mudah dipahami report author;
dan filter propagation menjadi bagian eksplisit dari architecture.
Virtual relationship seperti TREATAS hanya berlaku pada calculation tertentu.
Karena itu untuk association bisnis yang fundamental, physical model biasanya tetap lebih mudah dikelola.
Checklist Sebelum Membuat Direct *:* Relationship
Sebelum memilih Many-to-many pada Cardinality, tanyakan beberapa hal berikut.
| Pertanyaan | Implikasi |
|---|---|
| Apakah kedua tabel dimension? | Pertimbangkan bridge table |
| Apakah kedua tabel fact? | Pertimbangkan shared dimensions/star schema |
| Apakah salah satu fact mempunyai grain lebih tinggi? | *:* mungkin memang diperlukan |
| Mengapa kedua key duplicate? | Validasi grain dan data quality |
| Apakah duplicate merupakan data valid? | Jangan hapus sembarangan |
| Apakah filter direction jelas? | Hindari accidental bidirectional filtering |
| Apakah model mempunyai multiple filter paths? | Periksa ambiguity |
| Apakah totals additive? | Validasi interpretasi |
| Apakah fact grain konsisten? | Pastikan summarization benar |
| Apakah report drill-down di bawah fact grain? | Gunakan measure untuk membatasi hasil |
Decision Framework Many-to-Many
Situasi pertama:
Dua dimension mempunyai many-to-many business relationship.
Contoh:
Customer ↔ Account.
Gunakan:
Bridge Table.
Situasi kedua:
Dua fact table mempunyai duplicate common key.
Contoh:
Order ↔ Fulfillment.
Pertimbangkan:
Shared dimensions + star schema.
Situasi ketiga:
Fact mempunyai grain lebih tinggi daripada dimension.
Contoh:
Target Category ↔ Product Dimension.
Direct many-to-many dapat menjadi desain yang valid, tetapi summarization harus dikontrol dengan measure.
Red Flags dalam Many-to-Many Model
Model Anda layak diperiksa kembali jika:
hampir seluruh relationship menggunakan *:*;
Both digunakan di hampir semua relationship;
developer tidak dapat menjelaskan grain;
bridge table tidak jelas;
fact table langsung saling berhubungan dalam jumlah besar;
grand total sulit dijelaskan;
duplicate sengaja dihapus agar model bekerja;
target pada category muncul seolah-olah target SKU;
banyak ambiguous paths;
atau relationship dibuat berdasarkan nama kolom tanpa memahami proses bisnis.
Best Practice: Nama Bridge Table Harus Jelas
Gunakan nama seperti:
BridgeCustomerAccount
BridgeSalespersonTerritory
BridgeProductPromotion
BridgeStudentCourse
atau:
CustomerAccount
SalespersonTerritory.
Nama yang jelas membantu developer memahami bahwa tabel tersebut menyimpan association, bukan dimension biasa.
Best Practice: Dokumentasikan Grain
Contoh dokumentasi:
| Table | Grain |
|---|---|
| DimCustomer | One row per customer |
| DimAccount | One row per account |
| BridgeCustomerAccount | One row per customer-account association |
| FactTransaction | One row per account transaction |
Dengan dokumentasi seperti ini, relationship menjadi jauh lebih mudah dipahami.
Best Practice: Sembunyikan Technical Columns
Surrogate key dan foreign key sering diperlukan oleh engine tetapi tidak berguna bagi report author.
Misalnya:
CustomerKey;
AccountKey;
BridgeCustomerKey;
BridgeAccountKey.
Jika tidak diperlukan untuk reporting, hide.
Expose:
Customer Name;
Account Name;
Category;
Segment;
dan business attributes lainnya.
Best Practice: Jelaskan Non-Additive Metrics kepada User
Jika report mempunyai joint ownership atau overlapping association, report user mungkin mempertanyakan grand total.
Microsoft menyarankan memberikan penjelasan kepada pengguna, misalnya melalui text box atau visual header tooltip, agar hasil many-to-many tidak disalahartikan.
Ini adalah contoh bahwa dashboard design bukan hanya persoalan calculation accuracy, tetapi juga communication.
Many-to-Many Tidak Selalu Buruk
Many-to-many sering mendapat reputasi buruk karena pengguna mendengar:
Hindari many-to-many.
Pernyataan tersebut terlalu sederhana.
Yang lebih tepat:
Hindari direct many-to-many yang tidak diperlukan.
Many-to-many merupakan konsep bisnis yang benar-benar ada.
Power BI menyediakan alat untuk memodelkannya.
Masalah muncul ketika cardinality *:* digunakan sebagai jalan pintas tanpa memahami grain dan filter propagation.
Kapan Direct *:* Relationship Justru Masuk Akal?
Salah satu contoh paling jelas adalah higher-grain fact.
Misalnya:
DimProduct berada pada Product grain.
FactTarget berada pada Category grain.
Category duplicate di DimProduct.
Category juga duplicate di FactTarget.
Dalam kondisi seperti ini direct *:* dapat menjadi desain yang memang diperlukan.
Namun Anda tetap harus mengontrol bagaimana target diringkas ketika report turun ke level Product.
Bridge Table vs Direct Many-to-Many
| Aspek | Bridge Table | Direct *:* |
|---|---|---|
| Umum untuk dimension-to-dimension | Ya | Tidak direkomendasikan |
| Entity IDs tetap unik | Ya | Tidak selalu |
| Model association eksplisit | Ya | Lebih sedikit |
| Relationship evaluation | Dapat menggunakan regular 1:* | Limited |
| Cocok untuk higher-grain fact | Tergantung desain | Bisa sangat relevan |
| Best practice antar dimension | Ya | Tidak |
Many-to-Many vs One-to-Many
| Aspek | One-to-Many | Many-to-Many |
|---|---|---|
| Notasi | 1:* | *:* |
| Unique side | Ada | Tidak dijamin |
| Penggunaan | Sangat umum | Lebih khusus |
| Relationship evaluation | Umumnya regular | Limited |
| Star schema | Pola utama | Digunakan pada skenario tertentu |
| Kompleksitas | Lebih mudah dipahami | Membutuhkan perhatian lebih |
Many-to-Many vs One-to-One
One-to-one:
1 ↔ 1
Key unik pada kedua sisi.
Many-to-many:
* ↔ *
Tidak ada guaranteed unique side.
Keduanya merupakan relationship khusus dibanding 1:*.
Namun masalah desainnya berbeda.
Pada 1:1 kita sering bertanya:
Haruskah dua tabel ini sebenarnya digabung?
Pada many-to-many kita sering bertanya:
Apakah saya membutuhkan bridge, shared dimension, atau memang direct *:*?
Troubleshooting: Hasil Many-to-Many Terlihat Salah
Jika hasil terlihat aneh, jangan langsung mengubah DAX.
Periksa secara berurutan:
grain kedua tabel;
relationship cardinality;
filter direction;
bridge table;
duplicate keys;
missing keys;
shared entities;
limited relationship;
dan additive behavior measure.
Troubleshooting: Semua Customer Menampilkan Total yang Sama
Ini dapat terjadi jika filter dari Customer berhenti di bridge dan tidak diteruskan menuju Account/Transaction.
Periksa relationship direction.
Dalam contoh Microsoft, relationship Account–AccountCustomer harus mengizinkan filter bergerak kembali menuju Account sehingga customer context dapat mencapai Transaction.
Troubleshooting: Grand Total Lebih Kecil dari Penjumlahan Row
Periksa apakah terdapat overlapping associations.
Contoh:
shared bank account;
product yang masuk beberapa promotion;
customer yang mempunyai beberapa membership;
territory yang dibagi dua salesperson.
Grand total dievaluasi dalam grand-total filter context, bukan selalu sebagai SUM dari row values yang terlihat.
Troubleshooting: Target Berulang di Setiap Product
Ini hampir selalu merupakan tanda mismatch grain.
Jika target berada pada Category, jangan menampilkan target mentah pada Product.
Gunakan measure yang memahami level scope.
Troubleshooting: Banyak Relationship Menjadi Ambiguous
Periksa bidirectional relationship.
Filter mungkin mempunyai lebih dari satu jalur untuk bergerak dari satu tabel ke tabel lain.
Kurangi Both jika tidak diperlukan dan sederhanakan topology model.
Prinsip Utama Many-to-Many
Many-to-many adalah masalah business modeling terlebih dahulu, baru masalah cardinality.
Mulai dari memahami business relationship.
Setelah itu tentukan:
grain;
dimension;
fact;
association;
bridge;
filter flow;
dan calculation behavior.
Baru kemudian tentukan cardinality Power BI.
FAQ: Many-to-Many Relationship Power BI
Apa itu Many-to-Many Relationship di Power BI?
Many-to-many merupakan hubungan ketika satu nilai atau entity dapat berhubungan dengan beberapa nilai pada entity lain dan sebaliknya. Dalam Power BI, direct *:* cardinality memungkinkan duplicate values pada kedua relationship columns.
Apakah relationship bisnis many-to-many harus menggunakan cardinality *:*?
Tidak. Untuk dua dimension, Microsoft justru merekomendasikan bridge table yang menghubungkan kedua dimension menggunakan relationship one-to-many.
Apa itu bridge table?
Bridge table adalah tabel penghubung yang menyimpan satu baris untuk setiap association antara dua entity. Contohnya CustomerID–AccountID.
Apa itu factless fact table?
Factless fact table adalah fact table yang tidak mempunyai measure numerik dan terutama menyimpan dimension keys atau event association. Bridge table yang hanya menyimpan keys merupakan salah satu contohnya.
Apakah bridge table harus ditampilkan kepada pengguna?
Biasanya tidak. Microsoft merekomendasikan menyembunyikan bridge jika field di dalamnya tidak dibutuhkan untuk reporting.
Apakah direct fact-to-fact many-to-many direkomendasikan?
Umumnya tidak. Microsoft merekomendasikan penggunaan star schema dengan dimension tables yang terhubung ke masing-masing fact menggunakan one-to-many relationships.
Apa itu higher-grain fact?
Higher-grain fact adalah fact table yang menyimpan data pada level agregasi lebih tinggi dibanding dimension yang terkait. Contohnya target pada level Category sementara Product dimension berada pada level individual Product.
Apakah many-to-many merupakan limited relationship?
Ya. Microsoft menjelaskan bahwa cardinality many-to-many menghasilkan limited relationship karena tidak terdapat guaranteed “one” side.
Apa risiko limited relationship?
Limited relationship memiliki perilaku evaluasi berbeda dari regular relationship, tidak menggunakan table expansion yang sama, dan pelanggaran referential integrity dapat menyebabkan unmatched rows tidak diperlakukan dengan cara yang sama seperti regular relationship.
Apakah saya harus menggunakan Both pada many-to-many?
Tidak selalu. Pada bridge-table design, satu bidirectional relationship mungkin diperlukan agar filter dapat melewati bridge menuju fact, tetapi penggunaan Both sebaiknya dibatasi hanya pada relationship yang memang membutuhkannya.
Mengapa grand total tidak sama dengan penjumlahan row?
Pada many-to-many, satu entity dapat muncul dalam beberapa group. Karena itu row values dapat bersifat non-additive dan grand total dievaluasi ulang berdasarkan filter context keseluruhan.
Apakah many-to-many buruk untuk Power BI?
Tidak. Many-to-many merupakan relationship bisnis yang valid. Yang perlu dihindari adalah penggunaan direct *:* tanpa memahami grain, filtering, dan alternatif desain seperti bridge table atau star schema.
Kesimpulan
Many-to-Many Relationship merupakan salah satu topik terpenting dalam data modeling Power BI karena menggambarkan banyak situasi bisnis nyata yang tidak dapat direpresentasikan hanya dengan relationship one-to-many sederhana.
Namun konsep yang paling penting untuk dipahami adalah bahwa many-to-many business relationship tidak selalu berarti Anda harus membuat direct many-to-many cardinality di Power BI.
Untuk relationship antara dua dimension, Microsoft merekomendasikan menggunakan bridge table atau factless fact table. Kedua dimension mempertahankan unique ID masing-masing, sementara bridge menyimpan setiap association dan dihubungkan menggunakan relationship one-to-many. Pada kondisi yang membutuhkan filter propagation melalui bridge menuju fact table, salah satu relationship dapat menggunakan bidirectional filtering.
Untuk hubungan antara dua fact table, direct many-to-many memang secara teknis memungkinkan, tetapi Microsoft secara umum tidak merekomendasikannya sebagai desain utama. Shared dimensions dan star schema menghasilkan fleksibilitas filtering dan grouping yang lebih baik serta memungkinkan penggunaan regular one-to-many relationships.
Sementara itu, direct many-to-many cardinality mempunyai peran yang valid ketika bekerja dengan higher-grain facts. Target pada level Category, misalnya, dapat berhubungan dengan Product dimension yang berada pada level individual Product. Namun developer harus mengontrol summarization menggunakan explicit measures agar target Category tidak disalahartikan sebagai target Product.
Relationship many-to-many juga merupakan limited relationship. Ini berarti cara evaluasinya berbeda dengan regular one-to-many relationship, sehingga data integrity, filter propagation, dan pemahaman grain menjadi semakin penting.
Karena itu jangan memulai modeling dengan pertanyaan:
Bagaimana cara membuat relationship *:*?
Mulailah dengan:
Apa sebenarnya hubungan bisnis antara kedua entity ini?
Kemudian tanyakan:
Apa grain masing-masing tabel?
Lalu:
Apakah saya membutuhkan bridge table?
Atau:
Apakah kedua fact table seharusnya berbagi dimension?
Atau:
Apakah ini memang kasus higher-grain fact?
Baru setelah itu tentukan physical relationship yang sesuai.
Jika satu prinsip harus diingat dari seluruh pembahasan ini, prinsip tersebut adalah:
Jangan memilih cardinality berdasarkan apa yang membuat Power BI menerima relationship. Pilih cardinality berdasarkan grain dan realitas bisnis yang ingin direpresentasikan.
Semantic model Power BI yang baik bukan model dengan relationship paling sedikit atau paling banyak.
Model yang baik adalah model yang membuat hubungan antar data menjadi:
akurat, eksplisit, mudah dijelaskan, efisien, dapat diprediksi, dan sesuai dengan cara bisnis sebenarnya bekerja.
Referensi Utama
Microsoft Learn — Understand star schema and the importance for Power BI.
Microsoft Learn — Model relationships in Power BI Desktop, termasuk relationship evaluation, limited relationships, dan filter-path ambiguity.
Microsoft Learn — Bi-directional relationship guidance.







