Table.Group()

Learn how Table.Group aggregates rows into per-group summaries, the M equivalent of SQL's GROUP BY.

Table.Group()

Table.Group() groups a table's rows by one or more columns and computes an aggregation per group — the M equivalent of SQL's GROUP BY.

Table.Group(
    table as table,
    key as any,
    aggregatedColumns as list
) as table

Basic Example

#"Grouped Rows" = Table.Group(
    Source, {"Category"},
    {{"TotalSales", each List.Sum([SalesAmount]), type number}}
)
Source (one row per order)              Grouped Rows (one row per category)
Category | SalesAmount                  Category    | TotalSales
Bikes    | 500                          Bikes        | 1,250
Bikes    | 750                 -->      Accessories  | 300
Accessories | 300

Each aggregated column is defined as a triple: a name for the result column, a function run against each group's rows, and (optionally) the result type.


Multiple Aggregations at Once

#"Grouped Rows" = Table.Group(
    Source, {"Category"},
    {
        {"TotalSales", each List.Sum([SalesAmount]), type number},
        {"OrderCount", each Table.RowCount(_), Int64.Type},
        {"AvgSale", each List.Average([SalesAmount]), type number}
    }
)

The underscore _ inside an aggregation function refers to the current group — a table containing just that group's rows — which is what Table.RowCount(_) counts.


Grouping by Multiple Columns

#"Grouped Rows" = Table.Group(
    Source, {"Category", "Region"},
    {{"TotalSales", each List.Sum([SalesAmount]), type number}}
)
Category    | Region | TotalSales
Bikes       | West   | 800
Bikes       | East   | 450
Accessories | West   | 300

One output row per unique combination of the grouping columns — the same shape SQL's GROUP BY Category, Region would produce.


Table.Group vs. the Group By Button

The Group By button in the Power Query ribbon generates exactly this function — Table.Group() is what's actually running underneath, whether it was written by hand or generated by the UI.

UI (Group By button)Hand-written Table.Group
Speed to writeFaster for simple, single-aggregation groupingFaster once several aggregations are needed at once
FlexibilityLimited to the dialog's supported aggregationsAny M expression, including custom logic beyond sum/count/average

Common Mistakes

Forgetting the Result Type

Omitting the third element of each aggregation triple still works, but leaves the result column typed as any — worth adding explicitly (type number, Int64.Type) so downstream steps don't need an extra Table.TransformColumnTypes just to fix it.

Referencing the Wrong Table Inside an Aggregation

Inside an aggregation function, _ refers to the current group, not the original source table — using the original table's name instead of _ aggregates over everything, not just the current group's rows.

Grouping Before Cleaning the Data

Grouping locks in whatever's in the key columns at that point — a typo or inconsistent casing in a grouping column (e.g. "Bikes" vs "bikes") produces two separate groups instead of one. Clean and type the grouping columns before grouping, not after.


Best Practices

  • Add an explicit result type to every aggregation, rather than leaving it as any.
  • Use _ (the current group) inside aggregation functions, not the original source table.
  • Clean and type grouping columns before grouping — a mistake here silently produces extra groups instead of an error.
  • Prefer Table.Group directly (over the UI) once more than one or two aggregations are needed — it's easier to read and maintain as a single step.

Next Steps

Continue learning Power Query: