Advanced Power Query and M
SurveyWide RawOrdersExport ExchangeRates FactSalesAssignments
Unpivot the wide survey
- Load SurveyWide. Select StoreCode, StoreName, RegionKey → Unpivot Other Columns.
- Split Attribute on "-" into Month and Year. Build a real date (first of month) from them.
- Move Target-2026 into its own query (it is not a month) before unpivoting, then merge it back as a column.
- Open Advanced Editor and read the generated M top to bottom. Rename every step so the pipeline reads like a sentence.
Write a custom function
- Create a blank query with this function: (t as text) as nullable number => let s = Text.Remove(t, {"$"," ","U","S","D"}), n = try Number.From(s) otherwise null in n
- Name it fnCleanMoney. Invoke it on Unit Price via Add Column → Invoke Custom Function.
- Write a second function fnParseDate that tries three cultures in order: "en-US", "en-GB", then Date.FromText with no culture.
- Apply it to Order Dt and verify every row.
Parameters and a switchable environment
- Create a text parameter Environment with values Dev, Test, Prod.
- Create a query Config with a table mapping Environment → source path (use three copies of a CSV in three OneDrive folders).
- Make the main source step read the path from Config via a lookup on the parameter.
- Switch the parameter and refresh. Then publish and change the parameter in the Service (Settings → Parameters).
Look up the last known exchange rate
- Rates only exist on Mondays. For each FactSales row you need the EUR rate from the most recent Monday on or before OrderDate.
- Approach A (M): add WeekStart = Date.StartOfWeek([OrderDate], Day.Monday) to FactSales and merge on WeekStart = RateDate and Currency = "EUR".
- Approach B (M, harder): buffer ExchangeRates with Table.Buffer, then per row List.Max of dates ≤ OrderDate. Compare refresh time.
- Add Net Sales EUR = Net Sales × rate.
Folding-safe incremental pattern
- Create RangeStart and RangeEnd Date/Time parameters.
- Filter FactSales: OrderDate >= RangeStart and OrderDate < RangeEnd.
- Check View Native Query at that step. If it folds, you are ready for incremental refresh; if not, move the filter earlier.
Interview questions
- What is the difference between Table.Buffer and List.Buffer and when do they help?
- Explain "each" in M.
- How do you handle a merge where the key has different casing or trailing spaces?
- When does a query stop folding? Give five common breakers.
- Why does "Enter Data" not scale and what do you replace it with?
- What is the difference between Table.SelectRows with a date filter and applying the filter on a parameter for incremental refresh?
Assessment
After unpivoting SurveyWide correctly (Target excluded), row count is:
- 12
- 36
- 48
- 24
try Number.From("N/A") otherwise null returns:
- 0
- an error
- null
- "N/A"
Which step is most likely to stop query folding on SQL Server?
- Filter rows
- Rename column
- Add index column
- Remove column
Write an M function that takes a table and a list of column names and returns the table with those columns trimmed, cleaned and capitalized. Apply it to RawOrdersExport.
Table.TransformColumns with List.Transform to build the transform list.