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

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now! Learn more

Reply
asm495
Regular Visitor

Aggregating multiple key-value columns

I have some data in this format:

 

IdQuestion1Value1Question2Value2Question3Value3
aaaaPears4Apples2Oranges5
aaabOranges2Pears5Apples7
aaacKiwi1Oranges8Apples3

 

The options for each of the questions are the same. The values are all numerical.

 

What I would like to be able to do is to transform it to be in this format with multiple rows where the question options are all in one column and the values are all in one column.

 

IdQuestionOptionValue
aaaaQuestion1Pears4
aaaaQuestion2Apples2
aaaaQuestion3Oranges5
aaabQuestion1Oranges2
aaabQuestion2Pears5
aaabQuestion3Apples7
aaacQuestion1Kiwi1
aaacQuestion2Oranges8
aaacQuestion3Apples3

 

I cannot seem to find a way to achieve this. Does anyone have any suggestions please? Thanks!

2 ACCEPTED SOLUTIONS
HotChilli
Community Champion
Community Champion

Unpivot all columns except ID.

Select the Attribute column. Split it by delimiter (from Non-digit to digit).

Then Pivot the column Attribute.1 with Value in Values and choose Don't Aggregate in the advanced section.

View solution in original post

AntrikshSharma
Super User
Super User

@asm495 Here is another way to solve this, a bit complex, but good to know how to do purely using M language.

let
    Source = Table.FromRows (
        Json.Document (
            Binary.Decompress (
                Binary.FromText (
                    "i45WSgQCJR2lgNTEomIgbQLEjgUFOakgjhEQ+xcl5qWDeaZKsTpg9UkowkZIuk2RdZvD1CcDOd6Z5ZlAyhBFqwWycmOl2FgA",
                    BinaryEncoding.Base64
                ),
                Compression.Deflate
            )
        ),
        let
            _t = ( ( type nullable text ) meta [ Serialized.Text = true ] )
        in
            type table [
                Id = _t,
                Question1 = _t,
                Value1 = _t,
                Question2 = _t,
                Value2 = _t,
                Question3 = _t,
                Value3 = _t
            ]
    ),
    ChangedType = Table.TransformColumnTypes (
        Source,
        {
            { "Id", type text },
            { "Question1", type text },
            { "Value1", Int64.Type },
            { "Question2", type text },
            { "Value2", Int64.Type },
            { "Question3", type text },
            { "Value3", Int64.Type }
        }
    ),
    AddedCustom = Table.AddColumn (
        ChangedType,
        "Custom",
        each
            let
                TargetCols = Record.RemoveFields ( _, "Id" ),
                RecToList = Record.ToList ( TargetCols ),
                Questions = 
                    List.Select (
                        Record.FieldNames ( TargetCols ),
                        each Text.StartsWith ( _, "Question" )
                    ),
                SplitIntoGroups = List.Split ( RecToList, 2 ),
                ToRecords = 
                    List.Transform (
                        SplitIntoGroups,
                        each Record.FromList ( _, { "Option", "Value" } )
                    ),
                Result = 
                    Table.FromColumns (
                        { Questions } & Table.ToColumns ( Table.FromRecords ( ToRecords ) ),
                        type table [ Question = text, Option = text, Value = Int64.Type ]
                    )
            in
                Result,
        type table [ Question = text, Option = text, Value = Int64.Type ]
    ),
    RemovedOtherColumns = Table.SelectColumns ( AddedCustom, { "Id", "Custom" } ),
    ExpandedCustom = 
        Table.ExpandTableColumn (
            RemovedOtherColumns,
            "Custom",
            { "Question", "Option", "Value" },
            { "Question", "Option", "Value" }
        )
in
    ExpandedCustom

 

View solution in original post

5 REPLIES 5
AntrikshSharma
Super User
Super User

@asm495 Here is another way to solve this, a bit complex, but good to know how to do purely using M language.

let
    Source = Table.FromRows (
        Json.Document (
            Binary.Decompress (
                Binary.FromText (
                    "i45WSgQCJR2lgNTEomIgbQLEjgUFOakgjhEQ+xcl5qWDeaZKsTpg9UkowkZIuk2RdZvD1CcDOd6Z5ZlAyhBFqwWycmOl2FgA",
                    BinaryEncoding.Base64
                ),
                Compression.Deflate
            )
        ),
        let
            _t = ( ( type nullable text ) meta [ Serialized.Text = true ] )
        in
            type table [
                Id = _t,
                Question1 = _t,
                Value1 = _t,
                Question2 = _t,
                Value2 = _t,
                Question3 = _t,
                Value3 = _t
            ]
    ),
    ChangedType = Table.TransformColumnTypes (
        Source,
        {
            { "Id", type text },
            { "Question1", type text },
            { "Value1", Int64.Type },
            { "Question2", type text },
            { "Value2", Int64.Type },
            { "Question3", type text },
            { "Value3", Int64.Type }
        }
    ),
    AddedCustom = Table.AddColumn (
        ChangedType,
        "Custom",
        each
            let
                TargetCols = Record.RemoveFields ( _, "Id" ),
                RecToList = Record.ToList ( TargetCols ),
                Questions = 
                    List.Select (
                        Record.FieldNames ( TargetCols ),
                        each Text.StartsWith ( _, "Question" )
                    ),
                SplitIntoGroups = List.Split ( RecToList, 2 ),
                ToRecords = 
                    List.Transform (
                        SplitIntoGroups,
                        each Record.FromList ( _, { "Option", "Value" } )
                    ),
                Result = 
                    Table.FromColumns (
                        { Questions } & Table.ToColumns ( Table.FromRecords ( ToRecords ) ),
                        type table [ Question = text, Option = text, Value = Int64.Type ]
                    )
            in
                Result,
        type table [ Question = text, Option = text, Value = Int64.Type ]
    ),
    RemovedOtherColumns = Table.SelectColumns ( AddedCustom, { "Id", "Custom" } ),
    ExpandedCustom = 
        Table.ExpandTableColumn (
            RemovedOtherColumns,
            "Custom",
            { "Question", "Option", "Value" },
            { "Question", "Option", "Value" }
        )
in
    ExpandedCustom

 

I have tested this and this also works well. One thing that anyone else who uses this solution should be aware of is that it is required for the sequence of the original columns to be: Question,Value,Question,Value,...

 

My data wasn't in this sequence and I had to correct this before it would work.

Thank you for the reply, it is appreciated. I have not had the chance to try this as I was trying the simpler solution offered first. I will try and test this later also to see if it works.

HotChilli
Community Champion
Community Champion

Unpivot all columns except ID.

Select the Attribute column. Split it by delimiter (from Non-digit to digit).

Then Pivot the column Attribute.1 with Value in Values and choose Don't Aggregate in the advanced section.

This is brilliant and seems to do exactly what I need. In my real life scenario I did not have the columns so neatly named with numbers but I adapted the solution by splitting on a different delimiter.

Helpful resources

Announcements
Power BI DataViz World Championships

Power BI Dataviz World Championships

The Power BI Data Visualization World Championships is back! Get ahead of the game and start preparing now!

December 2025 Power BI Update Carousel

Power BI Monthly Update - December 2025

Check out the December 2025 Power BI Holiday Recap!

FabCon Atlanta 2026 carousel

FabCon Atlanta 2026

Join us at FabCon Atlanta, March 16-20, for the ultimate Fabric, Power BI, AI and SQL community-led event. Save $200 with code FABCOMM.

Top Solution Authors