Published on : Aug 24, 2026

Power BI Data Modeling Explained Through a Real Sales Dataset

The deeper modelling concepts a beginner tutorial skips, worked through a five-table sales dataset

5 Minutes Read
Rutvik Acharya, Principal Data Scientist at Atlassian

Rutvik Acharya

Principal Data Scientist Atlassian

Power BI Data Modeling Explained Through a Real Sales Dataset thumbnail

Power BI Data Modeling Explained Through a Real Sales Dataset

Most Power BI confusion that looks like a chart problem is actually a modelling problem wearing a chart's costume. A visual that shows the same total for every category, a time-intelligence function that silently returns blank, a filter that seems to affect the wrong table entirely, these are model symptoms, not visual bugs, and no amount of fiddling with the chart itself fixes them.

This guide goes one level deeper than the Power BI for Beginners tutorial, linked at the end, which covers the basics of fact tables, dimension tables, and a first relationship. Here, the dataset is closer to what a real sales team actually works with, five tables instead of three, including a dedicated date table, and the concepts, cardinality, cross-filter direction, and the mistakes that come from getting either wrong, get the fuller treatment a beginner tutorial doesn't have room for.

The dataset: five tables, not three

Table

Grain

Role

Orders

one row per order line

fact table

Customers

one row per customer

dimension table

Products

one row per product

dimension table

Region

one row per sales region

dimension table

Date

one row per calendar day

dimension table

Orders holds the transactional numbers: quantity, unit price, order date, and the foreign keys pointing to a customer, a product, and a region. Everything else describes something about one of those keys. This is a straightforward star schema: one fact table in the centre, several dimension tables around it, with the dimensions relating directly to the fact table.

Why a dedicated Date table, not just the order date column

Orders already has an order date column. It's tempting to skip building a separate Date table and just use that column directly for anything time-related. This works for basic filtering, but it breaks down in two specific, common situations.

A dedicated, continuous Date table is the recommended foundation for reliable time-intelligence calculations. Functions like year-over-year growth or a running total rely on a continuous, gapless calendar, every single day represented, not just the days that happen to have an order. Orders, on its own, only contains dates when something was actually sold, which has gaps, weekends with no orders, days with no activity in a particular region. A dedicated Date table, built to include every day in the relevant range regardless of whether anything happened that day, is what these functions are actually built to sit on top of.

A shared calendar keeps multiple fact tables consistent. A sales dataset that later grows to include a Returns table or a Marketing Spend table can join all of them to the same single Date table, giving every part of the model one consistent definition of a week, a quarter, and a fiscal year, rather than each fact table computing its own version of "this month" independently.

Cardinality: getting the "one" and the "many" right

Every relationship in this model should be one-to-many: one row in a dimension table can relate to many rows in the fact table. One customer, many orders. One product, many order lines. One calendar day, many orders placed that day.

Screenshot 2026-08-17 185353.png

One customer can appear once in the Customers table but many times in Orders. That is the practical meaning of one-to-many cardinality.

Getting the direction of that "one" and "many" backwards, or leaving it on Power BI's automatic guess without checking, is one of the most common sources of a model that looks fine until a total comes out wrong. If Customers were accidentally set as the "many" side of its relationship to Orders, a customer's total spend could be calculated incorrectly, since the model would be structured as if a single order could relate to many customer records rather than the other way round.

Where this bites people: trusting Power BI's auto-detected cardinality without opening the relationship and checking it. The automatic guess is usually right, but "usually" isn't "always," and a wrong guess doesn't throw an error, it just quietly produces wrong numbers.

Cross-filter direction: single is the safe default

Cross-filter direction controls whether a filter applied to a dimension table flows through to the fact table. In a standard star schema like this one, single-direction filtering, from the dimension into the fact table, is the correct default for every relationship. Filtering Region to "West" should filter Orders down to West region orders; that's single-direction filtering doing its job.

Single direction means the dimension filters the fact table. The fact table does not automatically filter the dimension back.

Screenshot 2026-08-17 185427.png

Bidirectional filtering allows the filter to flow the other way too, letting a filter on the fact table affect a dimension table. It's occasionally necessary for specific, more advanced model shapes, but turning it on by default across every relationship, because a specific visual isn't filtering the way someone expected, is a common way to create ambiguous filter paths: if Region and Products are both set to bidirectional, and both connect back to Orders, Power BI can end up with more than one possible way to apply a filter, and the result is a number that's technically calculated but doesn't mean what anyone expects. Leave relationships single-direction unless there's a specific, understood reason to change one.

Bidirectional filtering allows the filter to travel both ways, which can be useful in specific model designs but can also create ambiguous filter paths.

A worked example: total sales by region and category

Total Sales = SUMX(Orders, Orders[Quantity] * Orders[UnitPrice])

An illustrative result might look like this:

Region

Electronics

Furniture

Total

West

₹…

₹…

₹…

South

₹…

₹…

₹…

North

₹…

₹…

₹…

The exact values depend on the underlying Orders table; the important point is that each region-category intersection is being filtered through the correct dimension relationships.

This measure, placed on a matrix visual with Region[RegionName] on rows and Products[Category] on columns, only produces a genuinely correct cross-tabulation if both relationships, Region to Orders and Products to Orders, are properly one-to-many with single-direction filtering. If either relationship is misconfigured, the matrix will still render, it just won't show the number the model is supposed to be capable of showing, and nothing about the visual itself indicates that anything is wrong. This is the practical reason modelling gets checked first, before troubleshooting a visual that "looks wrong": the visual is frequently innocent.

How to diagnose a broken model

When a Power BI visual shows a suspicious number, check the model in this order:

  1. Check the dimension key. Is the key unique in the dimension table?

  2. Check the relationship columns. Are the correct key columns connected?

  3. Check cardinality. Is the dimension on the "one" side and the fact table on the "many" side?

  4. Check cross-filter direction. Is the filter flowing in the direction the model requires?

  5. Check relationship status. Is the required relationship active?

  6. Check the Date table. Is it continuous and correctly related to the fact table?

  7. Test with a simple matrix. Use one or two dimension fields and a basic measure before debugging a complicated visual.

Screenshot 2026-08-17 185525.png

A simple test visual is often faster than debugging a complicated chart. If the simple matrix is wrong, the problem is probably in the model rather than the visual.

Common mistakes

  • Skipping the dedicated Date table and using the order date column directly. Time intelligence functions and multi-fact-table consistency both depend on a proper, gapless calendar table that the raw fact table alone doesn't provide.

  • Trusting auto-detected cardinality without verifying it. A wrong cardinality guess doesn't error out, it just quietly produces wrong totals.

  • Turning on bidirectional filtering as a default troubleshooting step. It's a targeted tool for specific model shapes, not a general fix for a filter that isn't behaving as expected, and applying it broadly creates ambiguous filter paths.

  • Unnecessarily snowflaking a dimension table. Splitting Products into a separate Products and Category table, each with its own relationship back toward the fact table, adds complexity without a real benefit unless the category data genuinely needs to be shared and maintained separately.

  • Creating two active relationships between the same pair of tables. Power BI only allows one active relationship at a time between two tables; a second one has to stay inactive and be invoked explicitly in a measure, which is easy to forget once the model has grown past a handful of tables.

Where to go from here

If the fact table and dimension table basics covered here felt unfamiliar, Power BI for Beginners covers that foundation on a simpler three-table model before returning here. Once the model itself is solid, the KPI dashboard design guide covers what to actually build on top of it, and choosing the right chart for the question covers picking the right visual once the model can support it.

For the tool-choice question this guide doesn't cover, whether Power BI is the right platform to invest in over Tableau for your specific goals, Power BI vs Tableau vs Excel covers that decision separately.

Quiz

TEST WHAT YOU LEARNED

Question 1 of 15

Q1: According to this guide, what is often the true root cause behind a Power BI visual that appears to be behaving incorrectly?

FAQ

FREQUENTLY ASKED QUESTIONS

The beginner tutorial covers a simpler three-table model and the basics of building your first relationship. This guide goes deeper into a five-table model, a dedicated date table, cardinality troubleshooting, and cross-filter direction—the concepts that show up once a model grows past the basics.
It works for simple filtering, but time intelligence functions and multi-fact-table consistency both need a continuous, gapless calendar that a raw transactional date column doesn't provide on its own, since it only contains dates when something actually happened.
One row in a dimension table, like one customer, can relate to many rows in the fact table, like many orders from that customer. Getting this backwards is a common, quiet source of a model that produces wrong totals without any visible error.
Because it matches how a standard star schema is meant to work: a filter on a dimension table flows into the fact table it's connected to. Bidirectional filtering, applied broadly, can create ambiguous filter paths that produce numbers nobody intended.
In specific, more advanced model shapes where a filter genuinely needs to flow both directions for a particular, understood reason. It shouldn't be reached for as a general fix when a filter isn't behaving the way you expected.
A situation where Power BI has more than one possible route to apply a filter across the model, usually caused by multiple bidirectional relationships converging on the same table. The result is a number that calculates without erroring but doesn't mean what anyone expects.
Snowflaking is splitting a dimension table into multiple smaller related tables, for example separating product category into its own table joined back to Products. It adds real complexity to the model and is only worth it when that category data genuinely needs independent maintenance.
Yes, but only one relationship between a given pair of tables can be active at a time. A second relationship has to stay inactive and be explicitly invoked inside a specific measure, which is easy to forget in a growing model.
Open each relationship in Model view and check it directly rather than trusting the automatic detection. It's usually right, but verifying takes seconds and catching a wrong guess early avoids a much harder debugging session later.
This is the central lesson of this guide: a matrix or chart can render successfully on top of a broken relationship and still produce numbers that are technically calculated but not what the model should be capable of showing. Check the model before assuming the visual itself is at fault.
In a straightforward star schema, each dimension normally connects directly to the fact table through its relevant relationship. More advanced models can have additional relationships, including inactive relationships for different date roles.
Build a simple cross-tabulation, like total sales by region and by category, using two different dimension tables at once. If the numbers look plausible and change correctly as you filter, both underlying relationships are behaving as intended.
Not particularly; real business models often have considerably more tables than this. Five tables with a clean star schema is a realistic, manageable size for learning these concepts before scaling up to something larger.
The data model, specifically the cardinality and cross-filter direction of the relevant relationships, before assuming the visual or the measure itself is broken. Model issues are a more common root cause than they first appear.
The KPI dashboard design guide, linked above, is a natural next step, since a solid model is exactly what makes the stakeholder-driven design process in that guide actually achievable.