Wicked Smart Data
LearnArticlesAbout
Sign InSign Up
LearnArticlesAboutContact
Sign InSign Up
Wicked Smart Data

The go-to platform for professionals who want to master data, automation, and AI — from Excel fundamentals to cutting-edge machine learning.

Platform

  • Learning Paths
  • Articles
  • About
  • Contact

Connect

  • Contact Us
  • RSS Feed

© 2026 Wicked Smart Data. All rights reserved.

Privacy PolicyTerms of Service
All Articles
Generating Cross-Tabulated Reports in Power Query: Pivot, Aggregate, and Shape Data for Presentation

Generating Cross-Tabulated Reports in Power Query: Pivot, Aggregate, and Shape Data for Presentation

Power Query⚡ Practitioner19 min readAug 1, 2026Updated Aug 1, 2026
Table of Contents
  • Introduction
  • Prerequisites
  • Understanding What a Cross-Tab Actually Requires
  • Setting Up: The Realistic Dataset
  • Step 1: Grouping Before Pivoting
  • Step 2: The Pivot Operation — UI and M
  • Step 3: Adding a Grand Total Column
  • Step 4: Adding a Totals Row
  • Step 5: Controlling Column Order
  • Step 6: The Full Query — Assembled
  • Building Multi-Dimensional Cross-Tabs
  • Handling Dynamic Pivot Columns: The Real Production Problem
  • Pivoting on Non-Numeric Values: Count-Based Cross-Tabs

Generating Cross-Tabulated Reports in Power Query: Pivoting, Aggregating, and Shaping Data for Presentation-Ready Output

Introduction

Your stakeholder wants a report. Not the long, normalized table you've been living in for the past three weeks — the one with 80,000 rows, a date column, a region column, a product category column, and a revenue figure. They want something they can hand to the VP: regions across the top, product categories down the side, and revenue in the cells. A classic cross-tab. A pivot table that's already shaped, already labeled, already clean.

You could do this in Excel's PivotTable UI, sure. But the moment the source data refreshes next Monday, you're rebuilding it by hand. You could write a DAX measure in Power BI, but that means building a data model just for a report that lives in a spreadsheet. What you actually want is a transformation that runs automatically, produces a static, presentation-ready layout, and sits right in the middle of your existing Power Query workflow. That's exactly what we're building in this lesson.

By the end of this lesson, you'll be able to take normalized transactional data and transform it into cross-tabulated output — complete with totals rows, formatted headers, and aggregation logic — using Power Query's Pivot Column feature and supporting M functions. You'll understand not just how to click through the dialog, but what the generated M code is doing, how to control aggregation, and how to handle the edge cases that break pivot operations in production.

What you'll learn:

  • How the Table.Pivot function works under the hood, and how to control its aggregation behavior
  • How to combine grouping and pivoting to produce multi-level cross-tabs
  • How to add calculated totals rows and columns without leaving Power Query
  • How to handle dynamic column sets when your pivot values change between refreshes
  • How to troubleshoot the most common pivot failures: null values, duplicate keys, and type mismatches

Prerequisites

You should be comfortable with:

  • Navigating the Power Query Editor in Excel or Power BI
  • Writing basic M code in the Advanced Editor
  • The Table.Group function (at least conceptually)
  • Appending and merging queries

If pivoting is a completely new concept, spend 10 minutes with the basic Pivot Column UI in Power Query first, then come back here for the deeper treatment.


Understanding What a Cross-Tab Actually Requires

Before we write a single line of M, let's be precise about what a cross-tabulation is structurally — because the transformation has three distinct requirements, and most problems happen when people conflate them.

A cross-tab needs:

  1. Row keys — the field(s) that will become your row labels (e.g., Product Category)
  2. Column keys — the field whose values will become column headers (e.g., Region: "North," "South," "East," "West")
  3. Values — the numeric field that gets aggregated and placed at each row/column intersection (e.g., Revenue)

The normalized form has all three as columns in separate rows. The cross-tabulated form collapses the column-key field, distributes its distinct values across the header row, and aggregates the value field at every intersection. Power Query's pivot operation does this collapsing — but it requires that your data be pre-grouped correctly, or it will fail silently with nulls or loudly with errors.

Here's a minimal example. Start with this:

Region Product Category Revenue
North Electronics 42000
South Electronics 31000
North Furniture 18000
South Furniture 27000

The cross-tab should look like this:

Product Category North South
Electronics 42000 31000
Furniture 18000 27000

Simple enough here. In production, you'll have hundreds of thousands of rows, multiple transactions per region/category combination, new regions appearing mid-year, and someone asking why the totals don't match. That's what we'll handle.


Setting Up: The Realistic Dataset

Let's work with something close to a real scenario. We have a sales transaction table loaded into Power Query. Here's a representative sample — imagine 50,000 rows of this:

TransactionID Date Region SalesRep ProductCategory Revenue Units
T-10041 2024-01-08 Northeast Sarah Chen Electronics 8,400 12
T-10042 2024-01-08 Southeast Marcus Webb Furniture 3,200 8
T-10043 2024-01-09 Midwest Sarah Chen Electronics 6,750 9
T-10044 2024-01-09 Northeast Priya Nair Office Supplies 1,100 44
T-10045 2024-01-10 West Marcus Webb Furniture 4,900 11

Our goal: produce a cross-tab showing total revenue by ProductCategory (rows) and Region (columns), with a grand total column on the right.


Step 1: Grouping Before Pivoting

This is the step most tutorials skip, and it's the reason your pivots have nulls.

Table.Pivot expects at most one row per combination of your row key and column key. If your source table has five transactions where Region = "Northeast" and ProductCategory = "Electronics," the pivot doesn't automatically sum them. Depending on the aggregation function you specify, it'll either error or silently return the last value it encountered.

The correct workflow is: group first, then pivot.

Open the Advanced Editor and write a fresh query, or build on your existing one. Here's the grouping step:

let
    Source = SalesTransactions,

    // Step 1: Aggregate to one row per Region/Category combination
    Grouped = Table.Group(
        Source,
        {"ProductCategory", "Region"},  // group keys
        {
            {"TotalRevenue", each List.Sum([Revenue]), type number},
            {"TotalUnits",   each List.Sum([Units]),   type number}
        }
    )
in
    Grouped

After this step, your table looks like:

ProductCategory Region TotalRevenue TotalUnits
Electronics Northeast 142000 203
Electronics Southeast 98000 141
Electronics Midwest 87000 125
Furniture Northeast 54000 132
... ... ... ...

Now every combination appears exactly once. The pivot will work cleanly.

Why this matters: If you skip the grouping step and go straight to pivot, Power Query will ask you to choose an aggregation function in the dialog. Under the hood, it wraps the pivot in a List.Sum or List.Count. This works — but it's implicit, and it means you're mixing your aggregation logic into your pivot step. Keeping them separate makes debugging far easier. When revenue looks wrong, you can inspect the grouped table directly.


Step 2: The Pivot Operation — UI and M

With the grouped table ready, let's pivot the Region column. In the Power Query Editor UI:

  1. Select the Region column (click the column header)
  2. Go to Transform tab → Pivot Column
  3. In the dialog, set Values Column to TotalRevenue
  4. Expand Advanced Options and set Aggregate Value Function to Sum
  5. Click OK

The generated M code looks like this:

Pivoted = Table.Pivot(
    Grouped,
    List.Distinct(Grouped[Region]),  // the distinct column values
    "Region",                        // the column being pivoted
    "TotalRevenue",                  // the values column
    List.Sum                         // the aggregation function
)

Let's break this apart because every parameter matters in production:

  • List.Distinct(Grouped[Region]) — this dynamically extracts all unique region values and uses them as column headers. This is the default behavior from the UI, and it's both powerful and dangerous. More on that in a moment.
  • "Region" — the column whose values become headers
  • "TotalRevenue" — the column whose values fill the cells
  • List.Sum — the aggregation. Because we already grouped, each intersection has exactly one row, so List.Sum of a single value is just that value. But it's still correct to specify it explicitly.

After pivoting, your table looks like:

ProductCategory Northeast Southeast Midwest West
Electronics 142000 98000 87000 73000
Furniture 54000 61000 49000 38000
Office Supplies 31000 28000 22000 19000

That's your cross-tab. But we're not done — we need totals, clean formatting, and we need to harden it against data changes.


Step 3: Adding a Grand Total Column

Power Query doesn't have a built-in "add totals" button, but we can add a calculated column that sums across every region column. The challenge is that we can't hard-code column names if regions change. Here's the approach:

// Get the list of region columns (everything except ProductCategory)
RegionColumns = List.Difference(
    Table.ColumnNames(Pivoted),
    {"ProductCategory"}
),

// Add a GrandTotal column that sums across all region columns dynamically
WithTotal = Table.AddColumn(
    Pivoted,
    "Grand Total",
    each List.Sum(
        List.Transform(
            RegionColumns,
            (col) => Record.Field(_, col)
        )
    ),
    type number
)

This pattern — List.Transform over column names, using Record.Field to extract each value from the current row's record — is one of the most useful idioms in M for working with variable column sets. It works regardless of how many region columns exist.

Tip: Record.Field(_, col) is equivalent to _[col], but the dynamic version using a variable column name requires Record.Field. You cannot write _[RegionColumns{0}] and have it work — Power Query won't evaluate the index expression inside bracket notation.


Step 4: Adding a Totals Row

Adding a totals row is structurally similar but requires a different approach. We need to create a new single-row table and append it to the pivoted result.

// Build a totals record
TotalsRecord = Record.FromList(
    List.Transform(
        Table.ColumnNames(WithTotal),
        (col) =>
            if col = "ProductCategory"
            then "TOTAL"
            else List.Sum(Table.Column(WithTotal, col))
    ),
    Table.ColumnNames(WithTotal)
),

// Convert the record to a one-row table
TotalsRow = Table.FromRecords({TotalsRecord}),

// Append the totals row
WithTotalsRow = Table.Combine({WithTotal, TotalsRow})

The logic: for every column name, if it's our row-key column (ProductCategory), insert the label "TOTAL." Otherwise, sum all values in that column using Table.Column, which returns a list of all values in a given column.

Your final table now looks like:

ProductCategory Northeast Southeast Midwest West Grand Total
Electronics 142000 98000 87000 73000 400000
Furniture 54000 61000 49000 38000 202000
Office Supplies 31000 28000 22000 19000 100000
TOTAL 227000 187000 158000 130000 702000

Step 5: Controlling Column Order

When you use List.Distinct to generate column headers dynamically, the order of columns in the pivoted output depends on the order that distinct values appear in the source data — which is essentially random for most datasets. Your report will have regions in a different sequence every time if you don't lock it down.

Fix this by defining an explicit column order:

// Define your desired column order
DesiredRegionOrder = {"Northeast", "Southeast", "Midwest", "West"},

// Only keep regions that actually exist in the data
// (in case some are absent in a given period)
ExistingRegions = List.Intersect({
    DesiredRegionOrder,
    List.Distinct(Grouped[Region])
}),

// Also handle any unexpected new regions not in our list
NewRegions = List.Difference(
    List.Distinct(Grouped[Region]),
    DesiredRegionOrder
),

// Combine: known regions in order, then any new ones at the end
FinalRegionOrder = ExistingRegions & NewRegions,

// Now pivot using this ordered list instead of List.Distinct
Pivoted = Table.Pivot(
    Grouped,
    FinalRegionOrder,
    "Region",
    "TotalRevenue",
    List.Sum
),

Then reorder all columns:

ReorderedColumns = Table.ReorderColumns(
    WithTotalsRow,
    {"ProductCategory"} & FinalRegionOrder & {"Grand Total"},
    MissingField.Ignore  // MissingField.Ignore prevents errors if a column is absent
)

Warning: MissingField.Ignore is your safety net when a region that appeared last month disappears this month. Without it, Table.ReorderColumns throws an error if any column in the list doesn't exist. With it, the missing column is silently skipped — which is usually the right behavior for a presentation report.


Step 6: The Full Query — Assembled

Here's the complete, production-ready query in one block:

let
    Source = SalesTransactions,

    // Remove any rows with nulls in key fields
    Cleaned = Table.SelectRows(
        Source,
        each [Region] <> null
            and [ProductCategory] <> null
            and [Revenue] <> null
    ),

    // Step 1: Group to one row per Category/Region
    Grouped = Table.Group(
        Cleaned,
        {"ProductCategory", "Region"},
        {
            {"TotalRevenue", each List.Sum([Revenue]), type number}
        }
    ),

    // Step 2: Define column order (known regions first, new ones appended)
    DesiredRegionOrder = {"Northeast", "Southeast", "Midwest", "West"},
    ExistingRegions    = List.Intersect({DesiredRegionOrder, List.Distinct(Grouped[Region])}),
    NewRegions         = List.Difference(List.Distinct(Grouped[Region]), DesiredRegionOrder),
    FinalRegionOrder   = ExistingRegions & NewRegions,

    // Step 3: Pivot
    Pivoted = Table.Pivot(
        Grouped,
        FinalRegionOrder,
        "Region",
        "TotalRevenue",
        List.Sum
    ),

    // Step 4: Add Grand Total column
    RegionColumns = List.Difference(Table.ColumnNames(Pivoted), {"ProductCategory"}),

    WithTotalColumn = Table.AddColumn(
        Pivoted,
        "Grand Total",
        each List.Sum(
            List.Transform(RegionColumns, (col) => Record.Field(_, col))
        ),
        type number
    ),

    // Step 5: Add Totals row
    TotalsRecord = Record.FromList(
        List.Transform(
            Table.ColumnNames(WithTotalColumn),
            (col) =>
                if col = "ProductCategory"
                then "TOTAL"
                else List.Sum(Table.Column(WithTotalColumn, col))
        ),
        Table.ColumnNames(WithTotalColumn)
    ),

    TotalsRow     = Table.FromRecords({TotalsRecord}),
    WithTotalsRow = Table.Combine({WithTotalColumn, TotalsRow}),

    // Step 6: Enforce column order
    FinalColumnOrder = {"ProductCategory"} & FinalRegionOrder & {"Grand Total"},

    Result = Table.ReorderColumns(
        WithTotalsRow,
        FinalColumnOrder,
        MissingField.Ignore
    )

in
    Result

Building Multi-Dimensional Cross-Tabs

Sometimes one row dimension isn't enough. Maybe you need Year and Quarter as nested row labels, with regions as columns. This is where you need to think carefully before pivoting.

The approach: include all row-key fields in your Table.Group call, then pivot only on the column-key field.

// Group by Year, Quarter, AND ProductCategory
Grouped = Table.Group(
    Cleaned,
    {"Year", "Quarter", "ProductCategory"},
    {
        {"TotalRevenue", each List.Sum([Revenue]), type number}
    }
),

// Then pivot only Region
Pivoted = Table.Pivot(
    Grouped,
    FinalRegionOrder,
    "Region",
    "TotalRevenue",
    List.Sum
)

The result will have Year, Quarter, and ProductCategory as row keys, with region columns across the top. The visual hierarchy (Year > Quarter > Category) has to be enforced by sorting:

Sorted = Table.Sort(
    Pivoted,
    {
        {"Year",            Order.Ascending},
        {"Quarter",         Order.Ascending},
        {"ProductCategory", Order.Ascending}
    }
)

Tip: If you want to present this with blank cells creating a visual grouping (i.e., Year and Quarter only shown once per group, not repeated), that's a formatting concern better handled in Excel or Power BI rather than in Power Query. In Power Query, always keep your data fully denormalized with every field populated — collapsing repeated values makes the data structurally fragile.


Handling Dynamic Pivot Columns: The Real Production Problem

Here's the scenario that breaks most pivot implementations: a new region opens mid-year. In January, your data has four regions. In July, someone opens a branch in the Pacific Northwest, and now your data has five. Your query was hardcoded to expect four columns. Everything downstream breaks.

The List.Distinct approach handles new columns appearing, but it creates a different problem: any report, chart, or formula downstream that references specific column names by index or by name will break when a column shifts position or a new one appears in the middle.

The production solution has three parts:

1. Maintain a reference list of known regions in a separate query or table

Create a small lookup table — either hardcoded in M or loaded from a config table — that lists all valid regions in the desired order. This is your contract.

// In a separate query: RegionReference
let
    Regions = {"Northeast", "Southeast", "Midwest", "West", "Pacific Northwest"}
in
    Regions

2. In your pivot query, always intersect against this list first

ExistingRegions = List.Intersect({RegionReference, List.Distinct(Grouped[Region])}),

This gives you only regions that both exist in the data AND are in your reference list, in reference-list order.

3. Handle truly unexpected new values explicitly

UnknownRegions = List.Difference(List.Distinct(Grouped[Region]), RegionReference),

You can then either append them (as we did before), log them for review, or — in a strictcompliance scenario — raise an error:

// Raise a visible error if unknown regions appear
_ = if List.Count(UnknownRegions) > 0
    then error "Unknown regions detected: " & Text.Combine(UnknownRegions, ", ")
    else null,

This turns a silent data-quality problem into a loud, visible one — which is usually what you want in a production reporting pipeline.


Pivoting on Non-Numeric Values: Count-Based Cross-Tabs

Not every cross-tab is about revenue. Sometimes you're counting: how many transactions per region per category, how many support tickets per team per priority level, how many students passed each subject in each school.

The pattern is the same, but your aggregation changes in the Table.Group step:

Grouped = Table.Group(
    Cleaned,
    {"ProductCategory", "Region"},
    {
        {"TransactionCount", each Table.RowCount(_), type number}
    }
),

Table.RowCount(_) counts the rows in each group — effectively a COUNT(*). Then pivot as normal using List.Sum (which will just sum the counts, since there's one per group after grouping).

For percentage-based cross-tabs (e.g., % of total transactions by region), add a calculated column after pivoting, referencing the Grand Total:

WithPercentage = Table.AddColumn(
    WithTotalColumn,
    "% of Total",
    each if [Grand Total] = 0
         then 0
         else Number.Round([Grand Total] / GrandTotalOverall * 100, 1),
    type number
)

Where GrandTotalOverall is a scalar computed earlier:

GrandTotalOverall = List.Sum(Table.Column(WithTotalColumn, "Grand Total")),

Hands-On Exercise

Let's put this to work. Create a new blank query in Power Query using the following data pasted into a table in Excel, or entered directly using Table.FromRows in the Advanced Editor:

let
    RawData = Table.FromRows(
        {
            {"2024-Q1", "Northeast", "Electronics",     95400},
            {"2024-Q1", "Southeast", "Electronics",     71200},
            {"2024-Q1", "Midwest",   "Electronics",     60800},
            {"2024-Q1", "Northeast", "Furniture",       41000},
            {"2024-Q1", "Southeast", "Furniture",       52000},
            {"2024-Q1", "Midwest",   "Furniture",       38000},
            {"2024-Q1", "Northeast", "Office Supplies", 22000},
            {"2024-Q1", "Southeast", "Office Supplies", 19500},
            {"2024-Q1", "Midwest",   "Office Supplies", 17000},
            {"2024-Q2", "Northeast", "Electronics",    108000},
            {"2024-Q2", "Southeast", "Electronics",     84000},
            {"2024-Q2", "Midwest",   "Electronics",     72000},
            {"2024-Q2", "Northeast", "Furniture",       47000},
            {"2024-Q2", "Southeast", "Furniture",       58000},
            {"2024-Q2", "Midwest",   "Furniture",       43000},
            {"2024-Q2", "Northeast", "Office Supplies", 25000},
            {"2024-Q2", "Southeast", "Office Supplies", 21000},
            {"2024-Q2", "Midwest",   "Office Supplies", 18500}
        },
        type table [Quarter=text, Region=text, ProductCategory=text, Revenue=number]
    )
in
    RawData

Your tasks:

  1. Build a cross-tab with ProductCategory and Quarter as row keys, Region as columns, and Revenue as values. Sort by Quarter ascending, then ProductCategory ascending.
  2. Add a Grand Total column on the right.
  3. Add a TOTAL row at the bottom, but also add sub-total rows after each Quarter group (hint: you'll need to build the totals rows in a loop using List.Transform over distinct quarter values, then combine all pieces).
  4. Enforce the column order: ProductCategory, Quarter, Northeast, Southeast, Midwest, Grand Total.

Stretch goal: Modify the query so that if a fourth region (say, "West") were added to the source data, it would appear between Midwest and Grand Total automatically without breaking anything.


Common Mistakes & Troubleshooting

Problem: Pivot returns all nulls

Cause: Your data wasn't pre-grouped, and there are duplicate row/column key combinations. Table.Pivot with List.Sum should handle this — but if you specified a non-aggregating function like List.First, duplicates cause nulls.

Fix: Always group before pivoting. Check your grouped table for duplicate key combinations: add a count column in the group step and filter for rows where count > 1.


Problem: "Expression.Error: There were too many elements in the enumeration"

Cause: This error appears when Table.Pivot encounters more than one value for a given row/column key combination and you specified an invalid or null aggregation function.

Fix: Explicitly pass List.Sum, List.Average, List.Max, or another aggregator as the fifth parameter to Table.Pivot. Never leave it out in production queries.


Problem: Grand Total column shows null for some rows

Cause: One or more region columns contain null values (from intersections where no data exists). List.Sum of a list containing nulls returns null if all values are null, and the correct sum otherwise.

Fix: Replace nulls with 0 after pivoting, before computing totals:

NullsReplaced = Table.ReplaceValue(
    Pivoted,
    null,
    0,
    Replacer.ReplaceValue,
    RegionColumns
)

Run this step right after pivoting, before any totals calculations.


Problem: Column headers contain unexpected values (e.g., whitespace, different casing)

Cause: Your Region field has inconsistent values in the source — "northeast" vs "Northeast," "West " (trailing space) vs "West."

Fix: Clean the column before grouping:

Cleaned = Table.TransformColumns(
    Source,
    {{"Region", each Text.Proper(Text.Trim(_)), type text}}
)

Problem: The TOTAL row values are text, not numbers, causing sort or format issues

Cause: When you use Table.FromRecords to build the totals row, M infers the column types from the values. Since ProductCategory is text and contains "TOTAL," the entire table type may shift.

Fix: After combining the data table with the totals row, explicitly re-type the numeric columns:

TypedResult = Table.TransformColumnTypes(
    WithTotalsRow,
    List.Transform(RegionColumns & {"Grand Total"}, (col) => {col, type number})
)

Problem: Pivot column order is different every refresh

Cause: You're using List.Distinct(Grouped[Region]) which returns values in first-seen order, which depends on source data order.

Fix: Use the explicit ordering approach described in Step 5. Always define a canonical column order rather than relying on List.Distinct.


Summary & Next Steps

Cross-tabulated reports in Power Query require disciplined, sequential thinking: clean first, aggregate second, pivot third, enhance with totals fourth, harden against schema changes fifth. The biggest mistake practitioners make is treating the Pivot Column dialog as a one-click solution — it works in demos, but it breaks in production when data is messy, when source schemas shift, or when downstream consumers expect a consistent column layout.

The core M functions you're now working with — Table.Pivot, Table.Group, Table.AddColumn, Table.Combine, Record.FromList, List.Intersect, List.Difference — form a toolkit for almost any reshaping problem you'll encounter. The patterns here generalize: the Grand Total column logic works for any set of numeric columns, the dynamic column-ordering pattern works for any categorical field you're pivoting on.

What to explore next:

  • Unpivoting (the reverse operation): Table.Unpivot and Table.UnpivotOtherColumns are essential when you receive pre-pivoted data and need to normalize it before analysis. This is the complement to everything you learned here.
  • Using Table.TransformColumns for display formatting: Applying currency formatting or number rounding to your output columns before loading, so the result looks right directly in Excel without any cell formatting steps.
  • Parameterizing the pivot field: Instead of hardcoding "Region" as the column-key field, you can accept a parameter and let the user choose which dimension to pivot on — building a flexible report template from a single query.
  • Performance with large tables: For datasets above a few million rows, grouping in Power Query before pivoting may be slower than pushing the aggregation to the source (SQL, Databricks, etc.) and pivoting only the summary result in Power Query. Learn when to use query folding to keep aggregations at the source.

The cross-tab is one of the most-requested report formats in any organization. You can now build one that's robust, repeatable, and refresh-ready — without touching a PivotTable.

Learning Path: Power Query Essentials

Previous

Filtering and Sorting Rows in Power Query: Practical Techniques for Slicing Your Data

Related Articles

Power Query🌱 Foundation

Working with Binary Data in Power Query M: Reading, Parsing, and Converting Bytes to Structured Tables

16 min
Power Query🌱 Foundation

Filtering and Sorting Rows in Power Query: Practical Techniques for Slicing Your Data

16 min
Power Query🔥 Expert

Implementing Custom Table.Schema Validation and Type Enforcement Pipelines in Power Query M for Robust Data Quality Contracts

26 min

On this page

  • Introduction
  • Prerequisites
  • Understanding What a Cross-Tab Actually Requires
  • Setting Up: The Realistic Dataset
  • Step 1: Grouping Before Pivoting
  • Step 2: The Pivot Operation — UI and M
  • Step 3: Adding a Grand Total Column
  • Step 4: Adding a Totals Row
  • Step 5: Controlling Column Order
  • Step 6: The Full Query — Assembled
  • Building Multi-Dimensional Cross-Tabs
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting
  • Problem: Pivot returns all nulls
  • Problem: "Expression.Error: There were too many elements in the enumeration"
  • Problem: Grand Total column shows null for some rows
  • Problem: Column headers contain unexpected values (e.g., whitespace, different casing)
  • Problem: The TOTAL row values are text, not numbers, causing sort or format issues
  • Problem: Pivot column order is different every refresh
  • Summary & Next Steps
  • Handling Dynamic Pivot Columns: The Real Production Problem
  • Pivoting on Non-Numeric Values: Count-Based Cross-Tabs
  • Hands-On Exercise
  • Common Mistakes & Troubleshooting
  • Problem: Pivot returns all nulls
  • Problem: "Expression.Error: There were too many elements in the enumeration"
  • Problem: Grand Total column shows null for some rows
  • Problem: Column headers contain unexpected values (e.g., whitespace, different casing)
  • Problem: The TOTAL row values are text, not numbers, causing sort or format issues
  • Problem: Pivot column order is different every refresh
  • Summary & Next Steps