Power BI Mastery
👋 WELCOME

One tool, mastered end to end.

Every module below builds on the same Northside Bike Works repair-jobs dataset — the same one from the Data Analyst course, if you've taken it. Work through them in order: clean the data, model it, write DAX, design a report, then publish it for real.

Your 3-month path

Month 1

Get the data right

Power Query ETL and data modeling — the unglamorous work that makes everything after it easy.

Month 2

Speak DAX

From your first SUM() to CALCULATE() and filter context — the language every Power BI report is written in.

Month 3

Ship it

Design a report worth looking at, then publish, refresh, and share it like a real analyst.

Month 1 · Module 1
🧹

Power Query / ETL

Cleaning data before you build anything on top of it.

Why this matters: the step everyone wants to skip is the one that determines whether every chart downstream is trustworthy. Power Query is Power BI's built-in ETL (Extract, Transform, Load) tool.

1 Extract, Transform, Load

Extract connects to a source (a CSV, a database, an API). Transform is Power Query's job — fixing types, renaming columns, removing duplicates, splitting fields, filtering junk rows. Load sends the clean result into your data model.

2 Applied Steps

Every click you make in Power Query — change a type, rename a column, remove duplicates — becomes an Applied Step in a visible, re-orderable list on the right of the editor. That list is what makes a refresh work: next month's export gets the exact same cleanup replayed on it automatically.

3 Common transforms

Change Type → Whole Number / Decimal / Text / Date
Trim / Clean → strip whitespace and invisible characters
Split Column → e.g. "J. Ahmed" into First Name + Last Name
Remove Duplicates, Remove Rows With Errors
Unpivot Columns → turn wide monthly columns into tidy rows

These five cover the majority of real-world cleanup work — memorise the menu locations, not the theory.

4 Query folding

When your source is a database, Power Query can sometimes push your steps back to the database itself instead of pulling everything in first — this is query folding, and it's the difference between a refresh taking 3 seconds or 3 minutes.

Live dashboard — clean this export
RAW SOURCE FILE
JobTypeCostPrice
" flat repair ""$8""$25"
"FULL TUNE-UP""35""90"
"Puncture Repair""5.0""20"
"""10""30"
"Brake Adjustment""$10""$30"
AFTER POWER QUERY
JobTypeCostPrice
Flat Repair825
Full Tune-Up3590
Puncture Repair520
Brake Adjustment1030
  • Trim whitespace from JobType
  • Fix capitalisation (Proper Case)
  • Convert Cost/Price to Decimal Number (strip "$")
  • Remove rows with blank JobType

Exercises

  • Load the Jobs export into Power Query and inspect each column's detected data type.
  • Trim and Proper-Case the JobType column.
  • Convert Cost and Price to Decimal Number, stripping any currency symbols.
  • Remove rows with a blank JobType, and document why in a comment.
  • Reorder two Applied Steps and observe how the result can change.
📦 Capstone — Clean Import Pipeline

Document a repeatable Power Query recipe for the Jobs export: the exact ordered list of Applied Steps, plus one sentence explaining what each step protects against.

Recap quiz

Month 1 · Module 2
🔗

Data Modeling

Turning separate tables into one connected model.

Why this matters: a model built right makes every DAX measure after it simple. A model built wrong makes every measure a fight.

1 Star schema

A fact table holds the events you're measuring — here, Jobs (one row per repair). Dimension tables describe things you group and filter by — here, Customers. Connect them with a relationship, and you have a star: the fact table in the middle, dimensions around it.

2 Cardinality & cross-filter direction

Jobs → Customers is many-to-one: many jobs can point at one customer. Cross-filter direction decides which side's filters flow through the relationship — usually single-direction, from the "one" side (Customers) down to the "many" side (Jobs).

3 Why not one big flat table?

You could copy each customer's name and city onto every one of their job rows. It would work — until a customer moves city and now half their old jobs say the wrong place. A modeled star schema stores each fact once, in one place.

Live dashboard — build the relationship
Jobs
CustomerID (many)
Customers
CustomerID (one)

No relationship yet — the chart below can't resolve a City for any job.

Revenue by City — populates once Jobs and Customers are connected.

Exercises

  • Load Jobs and Customers into the same model.
  • Build the relationship on CustomerID in Model view.
  • Confirm the cardinality shows many-to-one and cross-filter direction is single.
  • Build one visual that only works correctly once the relationship exists.
📦 Capstone — Model Diagram

A one-page model diagram of Jobs + Customers with the relationship labelled, plus a "Revenue by City" chart proving it resolves correctly.

Recap quiz

Month 2 · Module 3
🧮

DAX Foundations

The language every Power BI number is written in.

Why this matters: DAX (Data Analysis Expressions) is how you turn a model into numbers on a page. Get the basics solid before Module 4 makes it powerful.

1 Measures vs. Calculated Columns

A Measure calculates on the fly, based on whatever's currently filtered on screen. A Calculated Column computes once per row and stores that fixed value forever. Rule of thumb: if the number should react to filters/slicers, it's a Measure.

2 SUM vs. SUMX

Total Revenue = SUM(Jobs[Price])                  -- straight column total
Total Revenue (X) = SUMX(Jobs, Jobs[Price])        -- same result, evaluated row by row

SUM totals one column directly. SUMX (and the other X functions) walk the table row by row, evaluating an expression fresh each time — needed when what you're summing isn't a plain column, e.g. SUMX(Jobs, Jobs[Price] - Jobs[Cost]).

3 Row context vs. filter context

Row context is "which row am I on right now" — it exists inside iterators like SUMX. Filter context is "which rows are currently visible" — set by slicers, filters, and whatever's on the report page around your Measure. Most of what a Measure does is react to filter context.

Live dashboard — DAX Playground

        
Result

Exercises

  • Write Total Revenue, Total Cost, and Total Margin as Measures.
  • Write Job Count using COUNTROWS.
  • Write Avg Job Value using DIVIDE (safer than plain / — it handles divide-by-zero).
  • Explain in one sentence why each of these is a Measure, not a Calculated Column.
📦 Capstone — Measures Table

A documented table of 8 core business Measures for the Jobs model — name, formula, and one-line description for each.

Recap quiz

Month 2 · Module 4
⚙️

Advanced DAX

CALCULATE, ALL(), and taking control of filter context.

Why this matters: CALCULATE is the single most powerful function in DAX — nearly every advanced measure you'll ever write is CALCULATE wearing a different filter.

1 CALCULATE fundamentals

High Value Revenue =
CALCULATE(
    SUM(Jobs[Price]),
    Jobs[Price] > 100
)

CALCULATE evaluates its first argument under a modified filter context — the extra arguments add, replace, or remove filters compared to what's currently on the report page.

2 ALL() — removing filters on purpose

Revenue % of Total =
DIVIDE(
    SUM(Jobs[Price]),
    CALCULATE(SUM(Jobs[Price]), ALL(Jobs))
)

ALL(Jobs) strips away whatever filters are currently applied to Jobs, giving you the unfiltered grand total to divide against — the classic "percent of total" pattern.

3 VAR ... RETURN

Margin % =
VAR TotalRevenue = SUM(Jobs[Price])
VAR TotalMargin = SUM(Jobs[Price]) - SUM(Jobs[Cost])
RETURN
    DIVIDE(TotalMargin, TotalRevenue)

Name an intermediate result once with VAR, then reuse it as many times as you like in RETURN — clearer to read, and often faster since it's calculated only once.

Live dashboard — filter context, side by side

Page filter: All

Revenue (plain measure)
Revenue — CALCULATE + ALL() (ignores page filter)
Revenue (plain) = SUM(Jobs[Price])
Revenue (ignore filter) = CALCULATE(SUM(Jobs[Price]), ALL(Jobs))

Click a status above — the plain measure reacts, the ALL() measure stays fixed at the grand total. That's filter context override in action.

Exercises

  • Write a CALCULATE measure for revenue from High Value jobs only (>$100).
  • Write a "% of Total Revenue by JobType" measure using ALL().
  • Rewrite one earlier measure using VAR/RETURN and compare readability.
📦 Capstone — % of Total Revenue by Job Type

A working measure and matching chart that shows each job type's share of total revenue, using CALCULATE + ALL().

Recap quiz

Month 3 · Module 5
📊

Visual Report

Designing a report page people actually want to read.

Why this matters: a technically correct report that's hard to read gets ignored. Design is part of the job, not decoration on top of it.

1 Choosing the right visual

Comparing categories → bar chart. Trend over time → line chart. One headline number → KPI card. Many categories of similar size → never a pie chart (past 4-5 slices they become unreadable — a sorted bar chart wins every time).

2 Slicers and layout

A slicer is a visible, clickable filter control on the page itself — no settings panel required. Put your KPI cards at the top (the headline), supporting charts below (the explanation) — match how people actually scan a page.

3 Bookmarks

A bookmark captures the current state of filters and visuals so a button can jump straight back to it — the basis of "guided" report navigation (e.g. a "Reset filters" button).

Live dashboard — a finished report page
Total Revenue
Jobs
Avg Margin %

Revenue by Job Type

Revenue Trend

Exercises

  • Build a report page with a KPI row, a category chart, and a trend chart.
  • Add a Status slicer that filters every visual on the page at once.
  • Apply one consistent colour per JobType across every visual.
  • Add a bookmark that resets all filters back to "All".
📦 Capstone — Finished Report Page

A complete, screenshot-ready report page combining KPI cards, a category chart, a trend chart, and a working slicer — designed to be handed to a manager, not just yourself.

Recap quiz

Month 3 · Module 6
☁️

Cloud Service

Publishing, refreshing, and sharing what you built.

Why this matters: a report sitting in Power BI Desktop on your laptop helps nobody. The Power BI Service (app.powerbi.com) is where it becomes real.

1 Workspaces vs. Apps

A Workspace is where you and collaborators build and edit. An App is the polished, read-only version you publish out to a wider audience — with its own curated navigation.

2 Scheduled refresh & gateways

The Service lives in the cloud; your source data might not. An on-premises data gateway is the secure bridge that lets a scheduled refresh reach into your private network to pull fresh data.

3 Row-Level Security

RLS lets you publish one report while each viewer only sees the rows relevant to them — a regional manager sees their region, not everyone's.

Live dashboard — publish workflow
1
Publish report to Workspace
2
Configure scheduled refresh (daily, 6am)
3
Publish as an App and share

Exercises

  • Publish your report from Desktop to a Workspace.
  • Set up a daily scheduled refresh.
  • Publish it as an App and share it with a view-only link.
  • Sketch a simple RLS rule: who should see which rows, and why.
📦 Capstone — Sharing Plan

A short written plan: who gets Workspace edit access, who gets the App, and what (if any) RLS rule protects which rows.

Recap quiz

Final Capstone
🏁

Ship one full Power BI solution

Every module, tied into one real deliverable.

Take a dataset — the Northside Bike Works set you've used throughout, or your own — and carry it through all six stages, end to end:

StageWhat "done" looks like
1. Power QueryA documented, repeatable cleanup recipe (Applied Steps)
2. Data ModelingA star-schema model with correct relationships and cardinality
3. DAX FoundationsA table of core Measures (Revenue, Cost, Margin, Count, Avg)
4. Advanced DAXAt least one CALCULATE-based measure (% of total, or a filtered KPI)
5. Visual ReportA finished report page: KPI row, category chart, trend chart, slicer
6. Cloud ServicePublished, on a refresh schedule, shared as an App
🎓 You're done when...
  • All six stages are complete for the same dataset.
  • You can explain, out loud, one design decision you made at each stage and why.
  • Someone outside your head could open the published App and understand the numbers without you in the room.