Skip to main content
cancel
Showing results for 
Search instead for 
Did you mean: 

Compete to become Power BI Data Viz World Champion! First round ends August 18th. Get started.

Reply
datanalysis
New Member

Create a new column with calculation using conditions

Hi I have input data that looks like this, and I'd like to create a view with a new column "Month on Month Change", calculating difference on col "Actual" between current month and last month for items fall under the same "Segment". 

 

Input:

SegmentSectionMonthYearExpectedActualExpected VS ActualOwner
TransportationGeneral1+112023102993David
TransportationGeneral2+10202399100-1David
TransportationGeneral3+9202391910David
TransportationGeneral4+82023100991David
AccommodationGeneral1+1120236670-4John
AccommodationGeneral2+10202367681John
AccommodationGeneral3+9202367670John
AccommodationGeneral4+8202367661John

 

i.e: 

Month on Month change Row 1 = blank as there is no previous month data available for this segment

Month on Month change Row 2 = 1 (calculation being: select 'Segment - Transportation',  use 'Actual 2+10' - 'Actual 1+11')

SegmentSectionMonthYearExpectedActualExpected VS ActualOwnerMonth on month change
TransportationGeneral1+112023102993David 
TransportationGeneral2+10202399100-1David1

 

Following this logic, the full Output will look like:

SegmentSectionMonthYearExpectedActualExpected VS ActualOwnerMonth on month change
TransportationGeneral1+112023102993David 
TransportationGeneral2+10202399100-1David1
TransportationGeneral3+9202391910David-9
TransportationGeneral4+82023100991David8
AccommodationGeneral1+1120236670-4John 
AccommodationGeneral2+10202367681John-2
AccommodationGeneral3+9202367670John-1
AccommodationGeneral4+8202367661John-1

 

Is there a way to acheive this in PowerQuery?

2 ACCEPTED SOLUTIONS
AlienSx
Super User
Super User

    s = your_table,
    f = (tbl) => 
        [rows = List.Buffer(Table.ToRecords(Table.Sort(tbl, "Month"))), 
        gen = List.Generate(
            () => [i = 0, r = rows{0} & [Month on month change = 0]],
            (x) => x[i] < List.Count(rows),
            (x) => [i = x[i] + 1, r = rows{i} & [Month on month change = rows{i}[Actual] - x[r][Actual]]],
            (x) => x[r]
        )][gen],
    group = Table.Group(s, "Segment", {"x", f}),
    z = Table.FromRecords(List.Combine(group[x]))

View solution in original post

dufoq3
Super User
Super User

Hi @datanalysis, different approach here.

 

Result

dufoq3_0-1714673044213.png

let
    fnShift = (tbl as table, col as text, shift as nullable number, optional newColName as text, optional _type as type) as table =>
        //v 3. parametri zadaj zaporne cislo ak chces posunut riadky hore, kladne ak dole, 4. je nepovinny (novy nazov stlpca), 5. je nepovinny typ
        let
            a = Table.Column(tbl, col),
            b = if shift = 0 or shift = null then a else if shift > 0
                then List.Repeat({null}, shift) & List.RemoveLastN(a, shift)
                else List.RemoveFirstN(a, shift * -1) & List.Repeat({null}, shift * -1),    
            c = Table.FromColumns(Table.ToColumns(tbl) & {b}, Table.ColumnNames(tbl) &
                ( if newColName <> null then {newColName} else
                    if shift = 0 then {col & "_Duplicate"} else
                    if shift > 0 then {col & "_PrevValue"} 
                    else              {col & "_NextValue"} )),
            d = Table.TransformColumnTypes(c, {List.Last(Table.ColumnNames(c)), if _type <> null then _type else type any})
        in
            d,
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCilKzCsuyC8qSSzJzM9T0lFyT81LLUrMAbIMtQ0NgZSRgZExiGdgBCQtLYEEiOuSWJaZohSrg9cEI21DA4QJYL2GBiARXUNijTDWtkQywRBGGBCr30TbAtkPBnB3oBjgmJycn5ubn0IoEMzMgIQ52AcmQMIrPyOPgH7UIDAzBxEWUPuJ0I7ifYhuc6j3idCN4nmIbjMUu2MB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Segment = _t, Section = _t, Month = _t, Year = _t, Expected = _t, Actual = _t, #"Expected VS Actual" = _t, Owner = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"Year", Int64.Type}, {"Expected", type number}, {"Actual", type number}, {"Expected VS Actual", type number}}),
    GroupedRows = Table.Group(ChangedType, {"Segment"}, {{"All", each 
        [ a = fnShift(_,"Actual",1, null, type number),
          b = Table.AddColumn(a, "Month on month change", (x)=> x[Actual] - x[Actual_PrevValue], type number),
          c = Table.RemoveColumns(b, {"Actual_PrevValue"})
        ][c], type table}}),
    CombinedAll = Table.Combine(GroupedRows[All])
in
    CombinedAll

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

View solution in original post

2 REPLIES 2
dufoq3
Super User
Super User

Hi @datanalysis, different approach here.

 

Result

dufoq3_0-1714673044213.png

let
    fnShift = (tbl as table, col as text, shift as nullable number, optional newColName as text, optional _type as type) as table =>
        //v 3. parametri zadaj zaporne cislo ak chces posunut riadky hore, kladne ak dole, 4. je nepovinny (novy nazov stlpca), 5. je nepovinny typ
        let
            a = Table.Column(tbl, col),
            b = if shift = 0 or shift = null then a else if shift > 0
                then List.Repeat({null}, shift) & List.RemoveLastN(a, shift)
                else List.RemoveFirstN(a, shift * -1) & List.Repeat({null}, shift * -1),    
            c = Table.FromColumns(Table.ToColumns(tbl) & {b}, Table.ColumnNames(tbl) &
                ( if newColName <> null then {newColName} else
                    if shift = 0 then {col & "_Duplicate"} else
                    if shift > 0 then {col & "_PrevValue"} 
                    else              {col & "_NextValue"} )),
            d = Table.TransformColumnTypes(c, {List.Last(Table.ColumnNames(c)), if _type <> null then _type else type any})
        in
            d,
    Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("i45WCilKzCsuyC8qSSzJzM9T0lFyT81LLUrMAbIMtQ0NgZSRgZExiGdgBCQtLYEEiOuSWJaZohSrg9cEI21DA4QJYL2GBiARXUNijTDWtkQywRBGGBCr30TbAtkPBnB3oBjgmJycn5ubn0IoEMzMgIQ52AcmQMIrPyOPgH7UIDAzBxEWUPuJ0I7ifYhuc6j3idCN4nmIbjMUu2MB", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [Segment = _t, Section = _t, Month = _t, Year = _t, Expected = _t, Actual = _t, #"Expected VS Actual" = _t, Owner = _t]),
    ChangedType = Table.TransformColumnTypes(Source,{{"Year", Int64.Type}, {"Expected", type number}, {"Actual", type number}, {"Expected VS Actual", type number}}),
    GroupedRows = Table.Group(ChangedType, {"Segment"}, {{"All", each 
        [ a = fnShift(_,"Actual",1, null, type number),
          b = Table.AddColumn(a, "Month on month change", (x)=> x[Actual] - x[Actual_PrevValue], type number),
          c = Table.RemoveColumns(b, {"Actual_PrevValue"})
        ][c], type table}}),
    CombinedAll = Table.Combine(GroupedRows[All])
in
    CombinedAll

Note: Check this link to learn how to use my query.
Check this link if you don't know how to provide sample data.

AlienSx
Super User
Super User

    s = your_table,
    f = (tbl) => 
        [rows = List.Buffer(Table.ToRecords(Table.Sort(tbl, "Month"))), 
        gen = List.Generate(
            () => [i = 0, r = rows{0} & [Month on month change = 0]],
            (x) => x[i] < List.Count(rows),
            (x) => [i = x[i] + 1, r = rows{i} & [Month on month change = rows{i}[Actual] - x[r][Actual]]],
            (x) => x[r]
        )][gen],
    group = Table.Group(s, "Segment", {"x", f}),
    z = Table.FromRecords(List.Combine(group[x]))

Helpful resources

Announcements
July 2025 community update carousel

Fabric Community Update - July 2025

Find out what's new and trending in the Fabric community.

July PBI25 Carousel

Power BI Monthly Update - July 2025

Check out the July 2025 Power BI update to learn about new features.

Top Solution Authors