PowerQuery/M-Language Cheatsheet

Cheatsheet for PowerQuery with PowerBI or Excel

Power Query is query language which makes use of the M langauge to transform, manipulate, and query data and is used in different MS data applications such as PowerBI and Excel

Primitives and Operators

Power Query provides some basic literals such as numbers, text, booleans, and lists and they can be defined like so:

Type Example
Number 0, 10, 9999
Text "Hello world"
Logical true, false
list {"hello", 1}, hello

Additionally, there are the usual operators as well as some kind of special ones below:

Operator Example Result
Plus + 1 + 2 3
#time(12,23,0) + #duration(0,0,2,0) #time(12,25,0)
Combination & "Hello " & "world" "Hello world"
{1} & {2,3} {1,2,3}
[a = 1] & [b = 2] [a = 1, b = 2]
Not not Logical NOT
Or or Logical OR
And and Logical AND

Expressions

An expression is a part of a query that can be evaluated, such as "Hello" or Table.FromRows(Jeff, {"Name"})

Using variables in PowerQuery is done using using the let ... in expression where let defines a block in which variables can be assigned, each assignment separated by a , and in defines the block with the return expression

let
    data = Jeff,
    cols = {"Name"}
in
    Table.FromRows(data, cols)

Functions

Thera are also the function expression which can be defined using the following type of syntax for a single line function:

MyFunction = (param1, param2, paramN) => param1 + param2 + paramN

Or a more complex multi-line function making use of a let ... in expression and other function calls

CreateTable = (colName) =>
    let
        data = Jeff,
        cols = {colName}
    in
        Table.FromRows(data, cols)

And integrating that with the above let ... in expression will look something more like this in a query

let
    CreateTable = (colName) =>
        let
            data = Jeff,
            cols = {colName}
        in
            Table.FromRows(data, cols)
in CreateTable("Col Name")

Misc

Pivot Multi-Hot-Encoded Entries as Many Separate Ones

data

Id Started In Progress Completed
1 true false false
2 true true true
3 true true false

We can use the following query to pivot our table out like so:

= let
    Filter = (cond, stat) =>
        Table.AddColumn(
            Table.SelectColumns(
                Table.SelectRows(data, cond), {"Id"}
            ), "Stage", each stat
        ),

    initRows = Filter(each true, "Exists"),
    startedRows = Filter(each [Started], "Started"),
    progressRows = Filter(each [In Progress], "In Progress"),
    completedRows = Filter(each [Completed], "Completed")
in
    Table.Combine({initRows, startedRows, progressRows, completedRows})

Which will result in an output data table with:

result

Id Stage
1 Exists
2 Exists
3 Exists
1 Started
2 Started
3 Started
2 In Progress
3 In Progress
2 Completed

A Time-Period Based Target Table

Targets are often measured using metrics like YTD or MTD in PowerBI, however this may not be the optimal method as it may alternatively be useful to get the target as a running total for the time period

There's probably a better way to do this but the method I've worked it to create a running target table that only has columns for each target in it's own row which can then be linked to a Date/calendar table for making targets time-calculable:

= let 
    dates =  Table.FromColumns(
        {List.Dates(#date(2016, 1, 1), 2000, #duration(1, 0, 0, 0))}, {"Date"}
    ),

    AddTargetCol = (t, name, target) => Table.AddColumn(t, name, each (target/365)),

    withT1 = AddTargetCol(dates, "Target 1", 5000),
    withT2 = AddTargetCol(withT1, "Target 2", 10000),
    withT3 = AddTargetCol(withT2, "Target 3", 100)
in 
    withT3

Now, when measuring targets by time you can simply filter the appropriate time period and use a sum of time to display the time-appropriate target