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
Get the data right
Power Query ETL and data modeling — the unglamorous work that makes everything after it easy.
Speak DAX
From your first SUM() to CALCULATE() and filter context — the language every Power BI report is written in.
Ship it
Design a report worth looking at, then publish, refresh, and share it like a real analyst.
Power Query / ETL
Cleaning data before you build anything on top of it.
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.
| JobType | Cost | Price |
|---|---|---|
| " flat repair " | "$8" | "$25" |
| "FULL TUNE-UP" | "35" | "90" |
| "Puncture Repair" | "5.0" | "20" |
| "" | "10" | "30" |
| "Brake Adjustment" | "$10" | "$30" |
| JobType | Cost | Price |
|---|---|---|
| Flat Repair | 8 | 25 |
| Full Tune-Up | 35 | 90 |
| Puncture Repair | 5 | 20 |
| Brake Adjustment | 10 | 30 |
- ✓ 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.
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
Data Modeling
Turning separate tables into one connected model.
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.
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.
A one-page model diagram of Jobs + Customers with the relationship labelled, plus a "Revenue by City" chart proving it resolves correctly.
Recap quiz
DAX Foundations
The language every Power BI number is written in.
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.
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.
A documented table of 8 core business Measures for the Jobs model — name, formula, and one-line description for each.
Recap quiz
Advanced DAX
CALCULATE, ALL(), and taking control of filter context.
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.
Page filter: All
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.
A working measure and matching chart that shows each job type's share of total revenue, using CALCULATE + ALL().
Recap quiz
Visual Report
Designing a report page people actually want to read.
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).
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".
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
Cloud Service
Publishing, refreshing, and sharing what you built.
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.
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.
A short written plan: who gets Workspace edit access, who gets the App, and what (if any) RLS rule protects which rows.
Recap quiz
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:
| Stage | What "done" looks like |
|---|---|
| 1. Power Query | A documented, repeatable cleanup recipe (Applied Steps) |
| 2. Data Modeling | A star-schema model with correct relationships and cardinality |
| 3. DAX Foundations | A table of core Measures (Revenue, Cost, Margin, Count, Avg) |
| 4. Advanced DAX | At least one CALCULATE-based measure (% of total, or a filtered KPI) |
| 5. Visual Report | A finished report page: KPI row, category chart, trend chart, slicer |
| 6. Cloud Service | Published, on a refresh schedule, shared as an App |
- 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.