Download as pdf or txt
Download as pdf or txt
You are on page 1of 8

TODAY's MENU

HERE WE SERVE POWER QUERY M.

GROUPING DATA WITH A


CUSTOM COMPARER

DID YOU
KNOW?
Introduction
The 'Table.Group' function is a powerful data aggregation and
transformation function. Let's start with a quick review of its syntax.
For a more comprehensive exploration, you can quickly navigate to
my earlier post by scanning the QR code depicted below.

Function parameters:
table: the table to group
keyColumns: a list of column names to group the data by
aggregationColumns: a list with aggregation operation lists
groupKind: an enumeration, by default set to GroupKind.Global
(null or 1) to ensure unique keys are returned
comparer: a comparer function to adjust grouping

Table.Group( myTable,
{"myKeyColName"},
{
{newColName, operation, type},
{..}
},
optional groupKind,
optional comparer
)
Sample dataset with mock transactions
Transfer this code into a new blank query to try it yourself or work along.
let
Source = Table.FromRows(
{
{#date(2023, 2, 5), "CloudBliss Shopping", -30.99},
{#date(2023, 2, 5), "Grocery Store",-15.5},
{null, "Nature's Pantry", null},
{null, "Card number 564", null},
{#date(2023, 2, 5), "PowerPro Utilities", -90.0},
{null, "Period: January 2023", null},
{null, "Account: 123456789", null},
{null, "Reference Number: RST-7890", null},
{#date(2023, 2, 6), "Gourmet Bistro", -75.50},
{null, "Date: February 6, 2023", null},
{null, "123 Main Street, Anytown", null},
{null, "Card number 564", null},
{#date(2023, 2, 6), "TrustWise Bank", -150},
{null, "ATM cash withdrawl", null},
{null, "Location: 456 Oak Street, Anytown", null},
{null, "Card number 843", null},
{#date(2023, 2, 6), "HappyTimes: WDR-789012", 5}
}, type table [Date=date, Details=text, Debit=Currency.Type]
)
in
Source
The task: Combine all Details per transaction.
Depicted below, the first 10 rows from our sample dataset.

The goal is to return a single record for each transaction. Combining all
the data that is in the Details column (optionally also aggregating Debit)
Returning a table where the first 4 rows look like this:
The User Interface is there to assist you!
We can quickly generate the bulk of the syntax by leveraging the UI.
Here are the steps I am taking:

1. Although the Date column by itself is insufficient as Key, I require


it's value for my custom comparer logic. Therefore select it.
2. Choose “Group By” on the ribbon, set the dialog box to ‘Advanced’
3. The Date is placed in the keyColumns section, perfect.
4. Then it suggests to create a “Count” column, with a Count Rows
operation. Let's change that.
5. Set the New column name to Details, the operation to Sum and
apply that to the column Details
6. Add an aggregation. Set the New column name to Debit, the
operation to Sum and have that applied to the column Debit

Okay, there's still some work to be done...


Time to make magic happen!
Of course, you can't sum text strings, we all know that. A small change
is all we need: update List.Sum to Text.Combine and provide a space
as a separator to its second parameter, so it looks like this:

{"Details", each Text.Combine([Details], " "), type text}

One more thing to do: modify the grouping with a custom comparer.
We need to specify a fourth argument to be able to set the fifth.
Therefore, between the last }, and ), enter a comma, a null, and
another comma.

Comparers compare two values, that's why they are required to be


two-parameter functions. Enter this code: (a, b) => 1

We got all the table rows back but why?


A zero (0) means the current (a) and next value (b) are considered to
be equal and the row is placed in the current group. A one (1) means
they are not equal and a new group is created, here for each row.
Determining our custom comparison logic
Being able to see all rows in the table makes it easier to determine the
logic we require for the custom comparer. Basically we want to start a
new group when the next Date value is not null. Here we go.

(a, b) => b[Date] <> null

However this returns an Expression.Error: We cannot convert the


value true to type Number. Right, we've created a logical expression
that yields either true or false. Instead we need to obtain a 1 or 0.
Quick fix is wrapping Number.From around it to convert the result.

(a, b) => Number.From( b[Date] <> null )

Now isn't that magical!


I LOVE SOLVING
PRACTICAL PROBLEMS
WITH POWER QUERY/ M.

Melissa de Korte pqtodaysmenu

You might also like