6  Data Modeling

NoteWhat Is a Data Model?

A data model is the structure that sits beneath every Power BI report. It defines the tables in your dataset, the relationships between them, and the rules that govern how data flows from one table to another when a visual is filtered or a slicer is clicked. Before a single chart is placed on a report page, the data model must be designed correctly. A well-built model makes every downstream task, including writing measures, building visuals, and applying filters, faster, simpler, and more reliable. A poorly built model causes incorrect calculations, broken filters, and reports that are difficult to maintain.

This chapter covers the core concepts of data modeling in Power BI: how tables relate to each other, how to choose the right schema structure, how to build and manage relationships, and how to organize your model for clarity and performance.

NoteWhere Data Modeling Happens

Data modeling in Power BI Desktop takes place in the Model view, accessed by clicking the model icon on the left-side navigation bar. This view displays all the tables in your dataset as boxes, with lines drawn between them representing relationships. You can drag tables to reposition them, click relationship lines to inspect or edit them, and right-click tables or columns to access formatting and organizational options.

[Insert screenshot of the Power BI Desktop Model view showing several tables connected by relationship lines, with the model icon highlighted in the left navigation bar]

flowchart LR
    A[Load Tables\nvia Power Query] --> B[Model View]
    B --> C[Choose Schema\nStar or Snowflake]
    C --> D[Define Relationships]
    D --> E[Set Cardinality\n& Filter Direction]
    E --> F[Organize &\nHide Fields]
    F --> G[Validate\nthe Model]
    G --> H[Ready for\nReport Building]
    classDef default fill:#2e4057,color:#ffffff,stroke:#ff9933,stroke-width:3px,rx:10px,ry:10px;


6.1 Understanding the Data Model

6.1.1 Tables and Relationships Overview

NoteFact Tables and Dimension Tables

Every Power BI data model is built around two types of tables, each playing a distinct role.

A fact table holds the measurable, transactional data that your report analyses. Sales transactions, website events, purchase orders, and survey responses are all examples of fact table content. Fact tables tend to be tall and contain many rows, with columns that record what happened, when, how much, and to whom. They typically store numeric values such as revenue, quantity, and cost, alongside foreign key columns that link each row to its corresponding dimension entries.

A dimension table holds the descriptive attributes used to categorize, filter, and label the data in your fact table. A Customer dimension table holds customer names, regions, and segments. A Product dimension table holds product names, categories, and prices. A Date dimension table holds calendar attributes such as month names, quarter numbers, and financial year flags. Dimension tables tend to be shorter and narrower than fact tables.

The relationship between these two table types is what makes filtering work in a report. When a user clicks a region in a slicer, Power BI follows the relationship from the dimension table to the fact table and returns only the relevant rows.

NoteHow Relationships Work

A relationship in Power BI connects two tables through a shared column called a key. The key column in a dimension table is typically a unique identifier, for example a CustomerID or a ProductCode. The same identifier appears as a foreign key in the fact table, linking each transaction row back to its corresponding dimension entry.

When a relationship is in place, selecting a value in one table automatically filters the connected table. This propagation of filters across relationships is what makes interactive reports possible.

[Insert screenshot of the Model view showing a relationship line between a fact table and a dimension table, with the connecting key columns highlighted on both ends of the line]

6.1.2 Types of Schemas in Data Modeling

NoteWhat Is a Schema?

A schema defines how tables are organized and related to each other in a data model. It is the blueprint of your entire model structure. Choosing the right schema directly impacts query performance, data redundancy, ease of report building, and how well Power BI’s filter engine operates across your tables. In Power BI, the schema structure is visible in the Model view, where relationships between tables are drawn as connecting lines.

Power BI models typically follow one of three schema patterns: the Flat Schema, the Star Schema, and the Snowflake Schema.

Flat Schema

NoteWhat Is a Flat Schema?

In a flat schema, all data is stored in a single wide table with no separate dimension tables. Every attribute, both the measurable values and all the descriptive labels, is packed into one table. There are no relationships because there is only one table.

Example:

OrderID OrderDate CustomerName City ProductName Category Quantity Revenue
1001 01/01/2026 Vijay Hyderabad Laptop Electronics 2 80,000
1002 02/01/2026 Ravi Chennai Phone Electronics 1 25,000

Notice that CustomerName, City, ProductName, and Category repeat for every transaction. If a customer’s city changes or a product is renamed, every affected row must be updated individually.

TipWhen a Flat Schema Is Acceptable

A flat schema works for small, one-off datasets where simplicity is more important than scalability, such as a quick prototype report from a single exported CSV file. It requires no relationship setup and is easy for beginners to start with immediately.

WarningFlat Schemas Are Not Suitable for Production Models

Flat schemas have significant limitations at scale. Data redundancy inflates file size, making refreshes slower and the model heavier. Updating a product name or category requires changing many rows rather than one. Filter performance degrades as row counts grow. For any serious reporting work, restructure flat data into a star schema using Power Query before building the model.

Star Schema

NoteWhat Is a Star Schema?

The star schema is the most widely used and officially recommended schema for Power BI. It places a single fact table at the centre of the model, surrounded by multiple dimension tables that connect directly to it. The resulting shape, with one table at the middle and several others radiating outward, resembles a star.

Each dimension table connects to the fact table through a single, direct one-to-many relationship. There are no relationships between dimension tables themselves. This flat, direct structure gives Power BI the most efficient path for filtering and calculating across the model.

Microsoft officially recommends the star schema for Power BI because DAX and the VertiPaq engine are optimized to work with it.

NoteStar Schema Structure
Component Example Columns
FactSales (Fact Table) SalesID, DateID, CustomerID, ProductID, Revenue, Quantity
DimDate (Dimension) DateID, Day, Month, Quarter, Year, MonthName
DimProduct (Dimension) ProductID, ProductName, Category, Price
DimCustomer (Dimension) CustomerID, Name, City, Segment
DimRegion (Dimension) RegionID, RegionName, Country

flowchart TD
    DDate["📅 DimDate\nDateID, Day, Month, Quarter, Year"]
    DCustomer["👤 DimCustomer\nCustomerID, Name, City, Segment"]
    DProduct["📦 DimProduct\nProductID, Name, Category, Price"]
    DRegion["🗺️ DimRegion\nRegionID, RegionName, Country"]
    Fact["⭐ FactSales\nSalesID, DateID, CustomerID\nProductID, RegionID\nRevenue, Quantity"]

    DDate -->|"1 : *"| Fact
    DCustomer -->|"1 : *"| Fact
    DProduct -->|"1 : *"| Fact
    DRegion -->|"1 : *"| Fact
    classDef default fill:#2e4057,color:#ffffff,stroke:#ff9933,stroke-width:3px,rx:10px,ry:10px;

TipWhy the Star Schema Works So Well in Power BI

The star schema’s strength comes from its simplicity. Every filter applied in a report travels a single, direct relationship from a dimension table into the fact table. There are no intermediate hops, no ambiguous paths, and no chains of relationships to traverse. Power BI’s filter engine handles this structure with the least computational effort, resulting in faster visuals and more predictable DAX behavior.

Snowflake Schema

NoteWhat Is a Snowflake Schema?

A snowflake schema is an extension of the star schema where dimension tables are further split into smaller, normalized sub-dimension tables. Instead of one DimProduct table containing both the product details and the category details, a snowflake model splits these into a DimProduct table and a separate DimProductCategory table, connected by their own relationship. The result resembles a snowflake shape, with multiple layers of tables branching outward from the fact table.

The snowflake schema reduces data redundancy by storing each piece of descriptive information only once in its own table. It is common in data warehouses built for storage efficiency, and you will frequently encounter it when connecting Power BI to an enterprise database source.

NoteSnowflake Schema Structure
Component Example Columns
FactSales (Fact Table) SalesID, DateID, CustomerID, ProductID, Revenue
DimProduct (Dimension) ProductID, ProductName, CategoryID
DimProductCategory (Sub-Dimension) CategoryID, CategoryName, SubCategoryName
DimCustomer (Dimension) CustomerID, Name, CityID
DimCity (Sub-Dimension) CityID, CityName, CountryID
DimCountry (Sub-Dimension) CountryID, CountryName, Region

flowchart TD
    DDate["📅 DimDate"]
    DCustomer["👤 DimCustomer\nCustomerID, Name, CityID"]
    DCity["🏙️ DimCity\nCityID, CityName, CountryID"]
    DCountry["🌐 DimCountry\nCountryID, CountryName, Region"]
    DProduct["📦 DimProduct\nProductID, ProductName, CategoryID"]
    DCategory["🏷️ DimProductCategory\nCategoryID, CategoryName"]
    Fact["FactSales\nSalesID, DateID\nCustomerID, ProductID\nRevenue"]

    DDate -->|"1 : *"| Fact
    DProduct -->|"1 : *"| Fact
    DCustomer -->|"1 : *"| Fact
    DCategory -->|"1 : *"| DProduct
    DCity -->|"1 : *"| DCustomer
    DCountry -->|"1 : *"| DCity
    classDef default fill:#2e4057,color:#ffffff,stroke:#ff9933,stroke-width:3px,rx:10px,ry:10px;

WarningAvoid the Snowflake Schema in Power BI When Possible

In Power BI, each additional relationship hop between sub-dimension tables adds complexity for both the filter engine and the report builder. Filters must travel through multiple tables to reach the fact table, which slows performance and can produce ambiguous DAX results. The Model view also becomes harder to read and navigate as sub-dimension chains grow longer.

When your source data arrives in a snowflake structure, the recommended approach is to flatten it into a star schema using Merge Queries in Power Query. Merge the sub-dimension tables into their parent dimension so that each dimension table is self-contained, then connect the flattened dimension directly to the fact table. This preserves the normalization benefits of the source system while giving Power BI the star schema it performs best with.

Choosing the Right Schema

NoteSchema Comparison at a Glance
Feature Flat Schema Star Schema Snowflake Schema
Number of tables One Few Many
Relationships None Direct Chained
Data redundancy Very high Moderate Low
Query performance Poor at scale Excellent Slower
Report building ease Simple Simple Complex
DAX compatibility Limited Optimal Reduced
Recommended for Power BI Prototypes only Yes, always Flatten first

6.2 Building and Managing Relationships

6.2.1 Creating and Managing Relationships

NoteHow Power BI Detects Relationships Automatically

When you load tables into Power BI, the engine scans column names and values for patterns that suggest a relationship. If it finds two columns with identical names or matching values across tables, it automatically creates a relationship between them. These auto-detected relationships appear in the Model view as soon as the tables are loaded.

Auto-detection is a useful starting point, but it is not always accurate. Always review every automatically created relationship before building your report to confirm it connects the correct columns and uses the correct cardinality and filter direction settings.

[Insert screenshot of the Model view showing auto-detected relationship lines between newly loaded tables]

Creating a Relationship Manually

NoteHow to Create a Relationship

To manually create a relationship between two tables:

  1. Open the Model view by clicking the model icon in the left navigation bar
  2. Locate the key column in the dimension table (for example, CustomerID in the DimCustomer table)
  3. Click and drag that column across to the corresponding foreign key column in the fact table (for example, CustomerID in FactSales)
  4. Release the mouse. A relationship line appears between the two tables
  5. Double-click the relationship line to open the Edit Relationship dialog and review and confirm the settings

[Insert screenshot of the Model view showing the drag action between two columns to create a relationship, with the resulting relationship line visible]

Editing and Deleting Relationships

NoteManaging Existing Relationships

To edit an existing relationship, double-click the relationship line in the Model view. The Edit Relationship dialog opens, showing the two tables, the connected columns, the cardinality setting, and the cross-filter direction. Make any changes needed and click OK to apply.

To delete a relationship, right-click the relationship line in the Model view and select Delete.

All relationships can also be managed through Home → Manage Relationships, which opens a flat list of every relationship in the model with options to create, edit, or delete them.

[Insert screenshot of the Manage Relationships dialog showing a list of all relationships with their table names, columns, cardinality, and active status]

6.2.2 Relationship Cardinality

NoteWhat Is Cardinality?

Cardinality describes how many rows in one table can match rows in another table across a relationship. Power BI requires you to specify cardinality for every relationship, as it determines how the filter engine propagates selections and how DAX resolves calculations across tables. Choosing the wrong cardinality does not always produce an immediate error, but it can produce silently incorrect results in your visuals and measures.

flowchart LR

    subgraph OTO ["One-to-One"]
        A2["Employee<br/>1 row per employee"] -->|"1 : 1"| B2["EmployeeDetails<br/>1 row per employee"]
    end

    subgraph MTM ["Many-to-Many"]
        A3["Products<br/>many"] -->|"** : **"| B3["Promotions<br/>many"]
    end

    subgraph OTM ["One-to-Many (Most Common)"]
        A1["DimCustomer<br/>1 row per customer"] -->|"1 : **"| B1["FactSales<br/>Many rows per customer"]
    end
    classDef default fill:#2e4057,color:#ffffff,stroke:#ff9933,stroke-width:3px,rx:10px,ry:10px;

One-to-Many

NoteOne-to-Many Cardinality

One-to-Many is the most common and most desirable relationship type in a Power BI data model. It means that for each row in the “one” side table (the dimension), there can be many matching rows in the “many” side table (the fact table). The key column on the “one” side must contain unique values with no duplicates.

Example: Each customer appears exactly once in DimCustomer, identified by a unique CustomerID. That same CustomerID can appear hundreds of times in FactSales, once for each purchase that customer made. This is a one-to-many relationship from DimCustomer to FactSales.

One-to-many relationships are the backbone of the star schema and are what Power BI’s filter engine is designed to traverse most efficiently.

One-to-One

NoteOne-to-One Cardinality

One-to-One means that each row in the first table matches at most one row in the second table, and vice versa. Both sides of the relationship must have unique values in the key column.

Example: An Employee table holds core information such as name, department, and hire date. A separate EmployeeDetails table holds extended attributes such as office location and parking permit number. Each employee has exactly one record in each table. The relationship between them is one-to-one.

One-to-one relationships are uncommon in reporting models. When you encounter them, consider whether the two tables could simply be merged into a single table in Power Query, removing the need for the relationship entirely.

Many-to-Many

NoteMany-to-Many Cardinality

Many-to-Many means that rows on both sides of the relationship can have multiple matches on the other side. Neither table’s key column contains only unique values.

Example: A Sales table contains orders, and each order can include multiple products. A Promotions table tracks discount campaigns, and each campaign can apply to multiple products. A single product can appear in multiple orders and be covered by multiple promotions simultaneously. No single unique identifier links one row in Sales to exactly one row in Promotions, making this a many-to-many relationship.

Many-to-many relationships require careful handling. Power BI supports them natively, but they can produce unexpected filter behavior and ambiguous aggregations. Where possible, resolve many-to-many relationships by introducing a bridge table that sits between the two tables, converting the structure into two cleaner one-to-many relationships.

WarningMany-to-Many Relationships Need Extra Care

When Power BI encounters a many-to-many relationship, it cannot determine a clear “one” side to filter from. This can cause measures to double-count values or filters to propagate in unexpected directions. Before accepting a many-to-many relationship in your model, investigate whether a bridge table or a Power Query transformation step can restructure it into two one-to-many relationships.

6.2.3 Cross-Filter Direction

NoteHow Filters Flow Between Tables

Cross-filter direction controls which way filters travel across a relationship when a user interacts with a report. Understanding filter direction is essential because it directly determines which visuals respond when a slicer is clicked or a chart segment is selected. Every relationship in Power BI has a filter direction setting, and choosing the wrong one is one of the most common causes of visuals that do not respond to filters as expected.

Single Direction

NoteSingle Cross-Filter Direction

In Single direction, filters flow from the “one” side of the relationship to the “many” side only. Selecting a value in the dimension table filters the fact table, but selecting a value in the fact table does not filter back into the dimension table.

Example: In a one-to-many relationship from DimCustomer to FactSales, clicking a customer name in a slicer filters FactSales to show only that customer’s transactions. However, filtering FactSales (for example, to show only sales above a certain amount) does not filter DimCustomer to reflect only the customers involved in those sales.

Single direction is the default and recommended setting for one-to-many relationships. It is predictable, performs well, and avoids circular filter issues.

[Insert screenshot of the Edit Relationship dialog with Cross Filter Direction set to Single, with the directional arrow between the two tables visible]

Both Directions

NoteBidirectional Cross-Filter Direction

In Both direction, filters flow freely in either direction across the relationship. A selection in either table filters the other, regardless of which side is the “one” and which is the “many”.

Example: Setting the DimCustomer to FactSales relationship to bidirectional means that if a visual filters FactSales to show only orders above a certain value, the DimCustomer table automatically reflects only those customers who placed such orders. A slicer listing customer names would then show only the customers relevant to the current FactSales filter context.

Bidirectional filtering is useful in specific scenarios, particularly when working with many-to-many relationships via bridge tables, or when a dimension table needs to filter another dimension table through a shared fact table.

[Insert screenshot of the Edit Relationship dialog with Cross Filter Direction set to Both, with bidirectional arrows illustrated]

WarningUse Bidirectional Filtering Sparingly

Enabling bidirectional cross-filtering on multiple relationships in the same model can create ambiguous filter paths, where Power BI cannot determine which route a filter should take between two tables. This causes errors in DAX measures and unpredictable visual behavior. Only enable bidirectional filtering when there is a clear and specific reason to do so, and test the impact on all measures in your model after making the change.

6.2.4 Active and Inactive Relationships

NoteWhy a Model Can Have Multiple Relationships Between Two Tables

Power BI allows only one relationship between any two tables to be active at a time. The active relationship is the one Power BI uses automatically when filtering across those two tables. However, you can define additional inactive relationships between the same two tables for use in specific DAX calculations.

The most common scenario for inactive relationships involves a Date dimension table connected to a fact table through multiple date columns. A Sales fact table might have an OrderDate, a ShipDate, and a DeliveryDate. You can only activate one of these relationships at a time, but you can create inactive relationships for the others and reference them explicitly in DAX measures when needed.

NoteActive vs. Inactive Relationships in the Model View

In the Model view, active relationships appear as solid lines between tables. Inactive relationships appear as dashed lines. Both are visible in the diagram, but only the active relationship is used by default in visuals and implicit calculations.

[Insert screenshot of the Model view showing one solid relationship line (active) and one dashed relationship line (inactive) between the same two tables, with labels identifying each]

TipUsing Inactive Relationships in DAX

To activate an inactive relationship for a specific calculation, use the USERELATIONSHIP DAX function inside a measure. This temporarily switches the active relationship for that calculation only, without changing the model’s default behavior for all other visuals. This pattern is covered in detail in the DAX chapters later in this book.


6.3 Setting Up the Date Table

6.3.1 The Date Table

NoteWhy Every Model Needs a Dedicated Date Table

Any Power BI report that involves time-based analysis, including charts grouped by month, year-to-date comparisons, or quarter-over-quarter growth, requires a dedicated Date dimension table in the model. A Date table contains one row for every calendar day within the range of your data, with columns for all the time attributes you need: year, month, quarter, week number, day name, month name, and any fiscal calendar attributes your organization uses.

Without a proper Date table, Power BI cannot correctly use DAX time intelligence functions such as TOTALYTD, SAMEPERIODLASTYEAR, or DATEADD. These functions rely on a continuous, unbroken calendar sequence and a correctly marked Date table to work as expected.

[Insert screenshot of a Date dimension table in the Table view showing columns for Date, Year, MonthNumber, MonthName, Quarter, WeekNumber, and DayOfWeek]

NoteMarking a Table as a Date Table

Once you have a Date table in your model, you must mark it so Power BI recognizes it for time intelligence purposes:

  1. Select the Date table in the Table view or Model view
  2. Go to Table Tools → Mark as Date Table
  3. In the dialog, select the column that contains unique date values (one row per day, no gaps, no duplicates)
  4. Click OK

[Insert screenshot of the Table Tools ribbon with “Mark as Date Table” highlighted and the resulting dialog showing the date column selection]

TipConnect the Date Table to Every Date Column in Your Fact Table

If your fact table has multiple date columns (OrderDate, ShipDate, DeliveryDate), create a relationship from the Date table to each one. Make the most frequently used date (usually OrderDate) the active relationship and set the others as inactive, to be activated selectively using USERELATIONSHIP in specific DAX measures.


6.4 Organizing and Polishing the Model

6.4.1 Hiding Fields and Organizing the Model

NoteWhy Model Organization Matters

As tables and columns accumulate, the Data pane visible when building reports can become cluttered with technical fields that report builders do not need, such as foreign key columns, internal ID fields, and system timestamps. A well-organized model hides these fields from the report view, surfaces only the columns that add analytical value, and groups related fields into clearly named display folders. This makes the report-building experience significantly faster and less error-prone, especially for team members who did not build the model themselves.

Hiding Fields

NoteHow to Hide a Column or Table

To hide a field from the report view (it remains in the model and can still be used in relationships and DAX):

  1. In the Model view or the Table view, right-click the column or table you want to hide
  2. Select Hide in Report View
  3. The field becomes greyed out in the Model view, indicating it is hidden, and disappears entirely from the Data pane when building reports

To hide multiple columns at once, hold Ctrl, click each column header, then right-click and select Hide in Report View.

[Insert screenshot of the right-click context menu on a column in the Model view showing the “Hide in Report View” option highlighted]

TipFields to Hide as a Standard Practice

As a general rule, hide the following types of fields from every model:

  • Foreign key columns in fact tables (such as CustomerID, ProductID) that exist only to support relationships and carry no analytical meaning on their own
  • Technical system columns such as row version numbers, internal flags, or audit timestamps that report consumers would never use
  • Index or surrogate key columns generated during data transformation

Keep only the columns that a report builder would meaningfully place on a visual, use in a filter, or reference in a slicer.

Display Folders

NoteGrouping Fields into Display Folders

Display folders group related columns and measures within a table into labelled folders in the Data pane, making large tables easier to navigate. For example, a Date dimension table with many columns can be organized into folders named “Calendar”, “Fiscal Year”, and “Week”, so report builders can quickly find the attribute they need.

To assign a field to a display folder:

  1. Select the column or measure in the Model view or Table view
  2. In the Properties panel on the right, find the Display folder field
  3. Type the folder name. Use a backslash to create nested folders, for example “DateYear”
  4. Press Enter. The field moves into the named folder in the Data pane

[Insert screenshot of the Properties panel showing the Display Folder field being filled in for a selected column, alongside the resulting folder structure visible in the Data pane]

Renaming Tables and Columns

NoteGiving Tables and Columns Meaningful Names

Column names set in Power Query carry through to the model, but sometimes you need to adjust names at the model level for clarity in the report view. To rename a table or column in the Model view, double-click the table header or column name, type the new name, and press Enter. Renaming at the model level does not affect the underlying Power Query step or the source data. The renamed label appears in the Data pane and in all visuals that use that field.

[Insert screenshot of a table header being renamed inline in the Model view]

6.4.2 Model Properties and Formatting

NoteSetting Column Properties in the Model

Beyond hiding and organizing, the model level is also where you configure how Power BI interprets and displays each column. These settings are applied in the Properties panel when a column is selected in the Model or Table view, and they affect the default behavior of that column across all report visuals.

Key properties to configure include:

  • Data type — confirm the correct type is set (Text, Whole Number, Decimal, Date, Boolean)
  • Format — set the display format for numbers and dates (currency symbol, decimal places, date format string)
  • Summarization — controls how Power BI aggregates a numeric column when placed in a visual. The options are Sum, Average, Minimum, Maximum, Count, Count Distinct, and Do Not Summarize. Set this to Do Not Summarize for ID columns and key fields that should never be aggregated
  • Data category — informs Power BI about the semantic meaning of certain columns, such as Country, City, Latitude, Longitude, Image URL, or Web URL. Setting the correct data category enables features like automatic map visualizations and image rendering in tables

[Insert screenshot of the Properties panel in the Model view showing the Format, Summarization, and Data Category fields for a selected column]

TipSet “Do Not Summarize” on All Key and ID Columns

By default, Power BI adds a sigma (∑) symbol to any numeric column, indicating it will be summed when placed on a visual. CustomerID, ProductID, OrderNumber, and similar key columns should never be summed. Select each of these columns in the Model view and set Summarization to Do Not Summarize to prevent them from being accidentally aggregated in a visual.


6.5 Data Model Best Practices

6.5.1 Data Model Best Practices

NoteBuild the Model Before the Report

The most common mistake beginners make is skipping data modeling entirely and placing raw tables directly onto report pages. This approach produces reports that appear to work initially but break as soon as more complex filtering, cross-table analysis, or DAX calculations are needed. Always define your relationships, set cardinality and filter direction, hide unnecessary fields, and verify your model structure before placing the first visual on a report page.

NoteKeep Fact Tables Lean and Dimension Tables Rich

Fact tables should contain measurements and foreign keys only. Descriptive attributes such as customer names, product categories, and region labels belong in dimension tables. If your fact table contains long text descriptions or repeated category labels, those attributes should be moved into a dimension table and replaced with a key column. This reduces model size and ensures that filters behave correctly.

NoteUse a Star Schema Wherever Possible

Aim for a star schema in every model. If your source data arrives in a snowflake or flat structure, use Power Query to reshape it into a star schema before loading it into the model. The performance and simplicity benefits of the star schema compound as your model and report grow in complexity.

NoteAlways Include a Dedicated Date Table

Every model that involves time-based analysis should include a dedicated Date dimension table containing one row per calendar day, marked as a Date table in Power BI. Connect this Date table to every date column in your fact tables using active and inactive relationships as appropriate.

NoteAvoid Bidirectional Relationships by Default

Set all relationships to Single cross-filter direction unless there is a specific and well-understood reason to use Both. Bidirectional relationships are a common source of ambiguous filter paths and incorrect measure results. If your model requires bidirectional filtering in a specific scenario, isolate it to that relationship only and test all measures after enabling it.

TipValidate the Model Before Publishing

Before publishing a report to the Power BI service, perform a model validation pass:

  • Confirm every relationship connects the correct columns and uses the correct cardinality setting
  • Test each slicer and filter to ensure it propagates correctly across all visuals on every report page
  • Check that hidden fields do not appear in the Data pane during report building
  • Verify that all numeric columns have the correct summarization setting
  • Confirm your Date table is marked and connected to all relevant date columns

A few minutes of model validation before publishing prevents hours of debugging after.

ImportantThe Data Model Is the Foundation of Everything

Every visual, every measure, every filter, and every interaction in a Power BI report ultimately depends on the data model beneath it. Time invested in building a clean, well-structured model pays dividends across every subsequent stage of report development. A strong model makes simple things easy and complex things possible. A weak model makes everything harder.


Summary

Concept Description
Schema Design
Star Schema Central fact surrounded by denormalised dimensions
Fact Tables Quantitative measurements at the grain of analysis
Dimension Tables Descriptive context such as date, product, or customer
Relationships and Calculations
Relationships Joins between tables that propagate filters during evaluation
Cardinality One-to-many, many-to-one, or many-to-many between tables
Cross-Filter Direction Single or both directions for filter propagation across joins
Hierarchies Drill paths such as Year–Quarter–Month–Day on a date dimension
Calculated Columns vs Measures Choosing the right calculation type for the right scenario