Seven lessons, about an hour and 20 minutes. You'll build a real Power BI model from Sahara Mart's actual three-month sales data — a proper star schema, not a single flat table.
The dataset for this module isn't one flat spreadsheet — it's four separate tables, deliberately, because that's how Power BI actually wants data structured. Understanding why is the whole foundation this module sits on.
| Fact table (Sales) | One row per transaction. This is where the numbers live — revenue, quantity. It's the biggest table by far, and it grows every day. |
| Dimension tables (Branches, Products, Calendar) | One row per "thing you'd group or filter by." Small, stable tables that describe the fact table's rows without repeating that description on every single transaction. |
The reason this separation matters: if branch name, city, product category and price all lived directly inside the Sales table, every single transaction row would repeat "Lekki, Lagos" or "Beverages, ₦1,200" over and over — and the moment a branch is renamed, you'd need to update thousands of rows instead of one. A star schema — one fact table surrounded by small dimension tables — keeps each fact in exactly one place.
Grain matters here just as it did in SQL: one row in Sales is one transaction. Get that wrong in your head and every relationship you build afterward will misbehave in ways that are hard to trace back to the cause.
Import all four tabs and Power BI won't automatically know that Sales.branch_id refers to Branches.branch_id — you have to build that relationship explicitly in Model view, dragging branch_id in Sales to branch_id in Branches. Skip this, or get the direction wrong, and totals silently misbehave.
A relationship should flow many-to-one: many Sales rows relate to one Branches row. Power BI defaults to this correctly most of the time when you drag the join — but if you ever see a warning about "many-to-many," stop and check which table actually has one row per key before proceeding, because a many-to-many relationship changes how totals filter in ways that are easy to miss until a number looks subtly wrong.
Once all three relationships (to Branches, Products, and Calendar) are built correctly, filtering your dashboard by branch, category, or date range works everywhere at once — that's the entire point of the model, and it's why this setup step, done once, saves rebuilding filter logic in every visual individually.
Two ways to add a calculation in Power BI, and choosing wrong is the most common beginner mistake. A calculated column computes a value for every row, stored permanently — expensive, and usually unnecessary. A measure computes on the fly, in response to whatever filter is currently applied — cheap, flexible, and almost always what you actually want.
Total Revenue = SUM(Sales[revenue])
This is a measure. It doesn't store a value anywhere — it recalculates instantly whenever a filter (branch, date range, category) changes, which is exactly the behaviour a dashboard needs.
A calculated column would make sense for something genuinely per-row and static — a "Price Band" label derived from unit_price, say. Almost everything you'll build in this module — totals, averages, percentages, comparisons — belongs as a measure, not a column.
"How's this month doing compared to last month" needs the Calendar table you imported — this is exactly why a proper date dimension exists rather than relying on the raw dates buried in Sales.
Revenue Last Month = CALCULATE([Total Revenue], DATEADD(Calendar[date], -1, MONTH))
CALCULATE changes the filter context; DATEADD shifts the date filter back one month. This pattern — CALCULATE wrapping a time-shift function — is the backbone of nearly every time-intelligence measure you'll ever write.
Build the reverse comparison too: MoM Change % = DIVIDE([Total Revenue] - [Revenue Last Month], [Revenue Last Month]). DIVIDE, not a plain slash, matters here — it handles a divide-by-zero gracefully (returning blank instead of an error) for any branch or period with no prior data.
Chidi has ten seconds, standing up, between meetings. A dashboard with fourteen visuals crammed onto one page fails him completely, however accurate every number on it is — the same lesson from module 2.4's pivot-table discipline, applied at dashboard scale.
Every visual you add after the fourth one is competing for the same ten seconds of attention as the first three. Most of them lose.
A dashboard that only updates when you personally open Power BI Desktop and hit refresh is a dashboard that will be stale the one week you're on leave. Publishing to the Power BI service and setting a scheduled refresh — daily, against the live source once one exists — is what turns a one-off report into a real operational tool.
Sahara Mart's nine branch managers should each see their own branch's numbers, not all nine — that's Row-Level Security (RLS), a rule applied at the data level so the same published report shows different rows to different viewers automatically, rather than maintaining nine separate copies of the same dashboard.
It will happen — a branch manager insists their branch's number on the dashboard is wrong. The wrong response is either defensive certainty ("the dashboard is correct") or immediate capitulation ("let me fix that"). The right response is verification, out loud, together.
Every dashboard will eventually be challenged. How you handle the challenge — calmly, systematically, without defensiveness — is what determines whether people keep trusting the dashboard afterward, more than whether this particular instance turned out to be a real bug or a misunderstanding.
Have Power BI Desktop installed and the dataset imported — this drill is a real build, not a written exercise.
Using the Power BI dataset, build a single-page operations dashboard for Sahara Mart, then defend every number on it.
Whether the whole module comes together as one working thing — a correct model, measures that use CALCULATE and DIVIDE properly, a page designed for a ten-second glance, and the discipline from lesson 6.7 to actually verify a number rather than just trust that it looks right.
Keep this Power BI file — module 7 automates the manual report you built by hand back in module 2, using Python, and the same underlying data shows up again from a different angle.