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

Register now to learn Fabric in free live sessions led by the best Microsoft experts. From Apr 16 to May 9, in English and Spanish.

Reply
GrantBrunton
Frequent Visitor

How to Pivot nested name/value data when values are multiple sized arrays

I have some data I'm getting from a GraphQL API that has a number of objects which can have groups of items linked to the objects.

There could be any number of items linked to the objects from 0 or more so the attributes of the items are recorded as name value pairs where the values are arrays of data for the items and the names are the attributes the items have.

 

Here is an example of the source JSON data:

 

{
  "data": {
    "objects": {
      "edges": [
        {
          "node": {
            "id": "4",
            "name": "ghi123",
            "deviceClass": {
              "id": "456",
              "class": "Class 2",
            },
            "configData": {
              "edges": [
                {
                  "node": {
                    "groups": [
                      {
                        "label": "Item 1",
                        "items": [
                          {
                            "name": "Name",
                            "values": [
                              "alpha",
                              "beta",
                            ]
                          },
                          {
                            "name": "Description",
                            "values": [
                              "stuff1",
                              "stuff2",
                            ]
                          },
                          {
                            "name": "Serial",
                            "values": [
                              "01FD6D30FCA3CA51A81BBC640E35032D",
                              "1B0EBF6E2B2C2FAF59693BE697855A29",
                            ]
                          }
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "id": "5",
            "name": "jkl456",
            "deviceClass": {
              "id": "456",
              "class": "Class 2",
            },
            "configData": {
              "edges": [
                {
                  "node": {
                    "groups": [
                      {
                        "label": "Item 1",
                        "items": [
                          {
                            "name": "Name",
                            "values": [
                              "james",
                              "simon",
                            ]
                          },
                          {
                            "name": "Description",
                            "values": [
                              "thing1",
                              "thing2",
                            ]
                          },
                          {
                            "name": "Serial",
                            "values": [
                              "0089FF209EEDBFED7089B5E1714B171948",
                              "1B0EBF6E2B2C2FAF59693BE697855A29",
                            ]
                          }
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          }
        },
        {
          "node": {
            "id": "6",
            "name": "mno789",
            "deviceClass": {
              "id": "789",
              "class": "Class 3",
            },
            "configData": {
              "edges": [
                {
                  "node": {
                    "groups": [
                      {
                        "label": "Item 1",
                        "items": [
                          {
                            "name": "Name",
                            "values": [
                              "sarah",
                              "Sally",
                              "Jane",
                              "Melissa",
                            ]
                          },
                          {
                            "name": "Description",
                            "values": [
                              "something1",
                              "something2",
                              "something3",
                              "something4"
                            ]
                          },
                          {
                            "name": "Serial",
                            "values": [
                              "1B0EBF6E2B2C2FAF59693BE697855A29",
                              "CCFD8BCBBCB4098D40383B993AE6C762",
                              "4DEBF92BED9C14E884D8AD59E00F693B",
                              "0089FF209EEDBFED7089B5E1714B171948",
                            ]
                          }
                        ]
                      }
                    ]
                  }
                }
              ]
            }
          }
        }
      ]
    }
  }
}

 

I've managed to input the data and get it into table form like so:

idnameclassitems.nameitems.value
4ghi123Class 2Namealpha
4ghi123Class 2Namebeta
4ghi123Class 2Descriptionstuff1
4ghi123Class 2Descriptionstuff2
4ghi123Class 2Serial01FD6D30FCA3CA51A81BBC640E35032D
4ghi123Class 2Serial1B0EBF6E2B2C2FAF59693BE697855A29
5jkl456Class 2Namejames
5jkl456Class 2Namesimon
5jkl456Class 2Descriptionthing1
5jkl456Class 2Descriptionthing2
5jkl456Class 2Serial0089FF209EEDBFED7089B5E1714B171948
5jkl456Class 2Serial1B0EBF6E2B2C2FAF59693BE697855A29
6mno789Class 3Namesarah
6mno789Class 3NameSally
6mno789Class 3NameJane
6mno789Class 3NameMelissa
6mno789Class 3Descriptionsomething1
6mno789Class 3Descriptionsomething2
6mno789Class 3Descriptionsomething3
6mno789Class 3Descriptionsomething4
6mno789Class 3Serial1B0EBF6E2B2C2FAF59693BE697855A29
6mno789Class 3SerialCCFD8BCBBCB4098D40383B993AE6C762
6mno789Class 3Serial4DEBF92BED9C14E884D8AD59E00F693B
6mno789Class 3Serial0089FF209EEDBFED7089B5E1714B171948

 

I'd like to pivot the items and end up with an output like below:

idnameclassItem NameItem DescriptionItem Serial
4ghi123Class 2alphastuff101FD6D30FCA3CA51A81BBC640E35032D
4ghi123Class 2betastuff21B0EBF6E2B2C2FAF59693BE697855A29
5jkl456Class 2jamesthing10089FF209EEDBFED7089B5E1714B171948
5jkl456Class 2simonthing21B0EBF6E2B2C2FAF59693BE697855A29
6mno789Class 3sarahsomething11B0EBF6E2B2C2FAF59693BE697855A29
6mno789Class 3Sallysomething2CCFD8BCBBCB4098D40383B993AE6C762
6mno789Class 3Janesomething34DEBF92BED9C14E884D8AD59E00F693B
6mno789Class 3Melissasomething40089FF209EEDBFED7089B5E1714B171948

 

The M code I have so far is below but I can't get the pivot part in the last step to work since there are multiple values to pivot on.

Any idea what I can do from here?

 

 

let
    Source = Json.Document(File.Contents("C:\Data.json")),
    #"Converted to Table" = Record.ToTable(Source),
    #"Removed Columns" = Table.RemoveColumns(#"Converted to Table",{"Name"}),
    #"Expanded Value" = Table.ExpandRecordColumn(#"Removed Columns", "Value", {"objects"}, {"objects"}),
    #"Expanded objects" = Table.ExpandRecordColumn(#"Expanded Value", "objects", {"edges"}, {"edges"}),
    #"Expanded edges" = Table.ExpandListColumn(#"Expanded objects", "edges"),
    #"Expanded edges1" = Table.ExpandRecordColumn(#"Expanded edges", "edges", {"node"}, {"node"}),
    #"Expanded node" = Table.ExpandRecordColumn(#"Expanded edges1", "node", {"id", "name", "deviceClass", "configData"}, {"id", "name", "deviceClass", "configData"}),
    #"Expanded deviceClass" = Table.ExpandRecordColumn(#"Expanded node", "deviceClass", {"class"}, {"class"}),
    #"Expanded configData" = Table.ExpandRecordColumn(#"Expanded deviceClass", "configData", {"edges"}, {"edges"}),
    #"Expanded edges2" = Table.ExpandListColumn(#"Expanded configData", "edges"),
    #"Expanded edges3" = Table.ExpandRecordColumn(#"Expanded edges2", "edges", {"node"}, {"node"}),
    #"Expanded node1" = Table.ExpandRecordColumn(#"Expanded edges3", "node", {"groups"}, {"groups"}),
    #"Expanded groups" = Table.ExpandListColumn(#"Expanded node1", "groups"),
    #"Expanded groups1" = Table.ExpandRecordColumn(#"Expanded groups", "groups", {"items"}, {"items"}),
    #"Expanded items" = Table.ExpandListColumn(#"Expanded groups1", "items"),
    #"Expanded items1" = Table.ExpandRecordColumn(#"Expanded items", "items", {"name", "values"}, {"items.name", "items.values"}),
    #"Expanded values" = Table.ExpandListColumn(#"Expanded items1", "items.values"),
    #"Pivoted Column" = Table.Pivot(#"Expanded values", List.Distinct(#"Expanded values"[items.name]), "items.name", "items.values")
in
    #"Pivoted Column"

 

 

1 ACCEPTED SOLUTION
MFelix
Super User
Super User

Hi @GrantBrunton ,

 

You need to follow the steps below:

  • Group rows:
    • ID
    • Name
    • Class
    • items.name
    • Select items values with all the value
  • Now redo the last part of the group rows step with the following syntax (ther part after the each:

 

Text.Combine([items.values], ","), type text
  •  Pivot by the column ITEMVALUES
  • Add custom column with the following code:
Table.RenameColumns(


Table.FromColumns ( { Text.Split([Name], ","),Text.Split([Description], ","),Text.Split([Serial], ",") }),

 {{"Column1", "Name"},{"Column2", "Description"},{"Column3", "Serial"}},
 
 
    MissingField.Ignore
)

 

  • Remove the Name, Description and Serial columns
  • Expand the new created column.

Check code below:

let
    Source = Json.Document(File.Contents("C:\Data.json")),
    #"Converted to Table" = Record.ToTable(Source),
    #"Removed Columns" = Table.RemoveColumns(#"Converted to Table",{"Name"}),
    #"Expanded Value" = Table.ExpandRecordColumn(#"Removed Columns", "Value", {"objects"}, {"objects"}),
    #"Expanded objects" = Table.ExpandRecordColumn(#"Expanded Value", "objects", {"edges"}, {"edges"}),
    #"Expanded edges" = Table.ExpandListColumn(#"Expanded objects", "edges"),
    #"Expanded edges1" = Table.ExpandRecordColumn(#"Expanded edges", "edges", {"node"}, {"node"}),
    #"Expanded node" = Table.ExpandRecordColumn(#"Expanded edges1", "node", {"id", "name", "deviceClass", "configData"}, {"id", "name", "deviceClass", "configData"}),
    #"Expanded deviceClass" = Table.ExpandRecordColumn(#"Expanded node", "deviceClass", {"class"}, {"class"}),
    #"Expanded configData" = Table.ExpandRecordColumn(#"Expanded deviceClass", "configData", {"edges"}, {"edges"}),
    #"Expanded edges2" = Table.ExpandListColumn(#"Expanded configData", "edges"),
    #"Expanded edges3" = Table.ExpandRecordColumn(#"Expanded edges2", "edges", {"node"}, {"node"}),
    #"Expanded node1" = Table.ExpandRecordColumn(#"Expanded edges3", "node", {"groups"}, {"groups"}),
    #"Expanded groups" = Table.ExpandListColumn(#"Expanded node1", "groups"),
    #"Expanded groups1" = Table.ExpandRecordColumn(#"Expanded groups", "groups", {"items"}, {"items"}),
    #"Expanded items" = Table.ExpandListColumn(#"Expanded groups1", "items"),
    #"Expanded items1" = Table.ExpandRecordColumn(#"Expanded items", "items", {"name", "values"}, {"items.name", "items.values"}),
    #"Expanded values" = Table.ExpandListColumn(#"Expanded items1", "items.values"),
    #"Grouped Rows" = Table.Group(#"Expanded values", {"id", "name", "class", "items.name"}, {{"ITEMVALUES", each Text.Combine([items.values], ","), type text }}),
    #"Pivoted Column" = Table.Pivot(#"Grouped Rows", List.Distinct(#"Grouped Rows"[items.name]), "items.name", "ITEMVALUES"),
    #"Added Custom" = Table.AddColumn(#"Pivoted Column", "Custom", each Table.RenameColumns(


Table.FromColumns ( { Text.Split([Name], ","),Text.Split([Description], ","),Text.Split([Serial], ",") }),

 {{"Column1", "Name"},{"Column2", "Description"},{"Column3", "Serial"}},
 
 
    MissingField.Ignore
)),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom",{"Name", "Description", "Serial"}),
    #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns1", "Custom", {"Name", "Description", "Serial"}, {"Name.1", "Description", "Serial"})
in
    #"Expanded Custom"

 

Be aware that if you have more columns you need to keep, then the grouping must be done by all of them.


Regards

Miguel Félix


Did I answer your question? Mark my post as a solution!

Proud to be a Super User!

Check out my blog: Power BI em Português



View solution in original post

2 REPLIES 2
MFelix
Super User
Super User

Hi @GrantBrunton ,

 

You need to follow the steps below:

  • Group rows:
    • ID
    • Name
    • Class
    • items.name
    • Select items values with all the value
  • Now redo the last part of the group rows step with the following syntax (ther part after the each:

 

Text.Combine([items.values], ","), type text
  •  Pivot by the column ITEMVALUES
  • Add custom column with the following code:
Table.RenameColumns(


Table.FromColumns ( { Text.Split([Name], ","),Text.Split([Description], ","),Text.Split([Serial], ",") }),

 {{"Column1", "Name"},{"Column2", "Description"},{"Column3", "Serial"}},
 
 
    MissingField.Ignore
)

 

  • Remove the Name, Description and Serial columns
  • Expand the new created column.

Check code below:

let
    Source = Json.Document(File.Contents("C:\Data.json")),
    #"Converted to Table" = Record.ToTable(Source),
    #"Removed Columns" = Table.RemoveColumns(#"Converted to Table",{"Name"}),
    #"Expanded Value" = Table.ExpandRecordColumn(#"Removed Columns", "Value", {"objects"}, {"objects"}),
    #"Expanded objects" = Table.ExpandRecordColumn(#"Expanded Value", "objects", {"edges"}, {"edges"}),
    #"Expanded edges" = Table.ExpandListColumn(#"Expanded objects", "edges"),
    #"Expanded edges1" = Table.ExpandRecordColumn(#"Expanded edges", "edges", {"node"}, {"node"}),
    #"Expanded node" = Table.ExpandRecordColumn(#"Expanded edges1", "node", {"id", "name", "deviceClass", "configData"}, {"id", "name", "deviceClass", "configData"}),
    #"Expanded deviceClass" = Table.ExpandRecordColumn(#"Expanded node", "deviceClass", {"class"}, {"class"}),
    #"Expanded configData" = Table.ExpandRecordColumn(#"Expanded deviceClass", "configData", {"edges"}, {"edges"}),
    #"Expanded edges2" = Table.ExpandListColumn(#"Expanded configData", "edges"),
    #"Expanded edges3" = Table.ExpandRecordColumn(#"Expanded edges2", "edges", {"node"}, {"node"}),
    #"Expanded node1" = Table.ExpandRecordColumn(#"Expanded edges3", "node", {"groups"}, {"groups"}),
    #"Expanded groups" = Table.ExpandListColumn(#"Expanded node1", "groups"),
    #"Expanded groups1" = Table.ExpandRecordColumn(#"Expanded groups", "groups", {"items"}, {"items"}),
    #"Expanded items" = Table.ExpandListColumn(#"Expanded groups1", "items"),
    #"Expanded items1" = Table.ExpandRecordColumn(#"Expanded items", "items", {"name", "values"}, {"items.name", "items.values"}),
    #"Expanded values" = Table.ExpandListColumn(#"Expanded items1", "items.values"),
    #"Grouped Rows" = Table.Group(#"Expanded values", {"id", "name", "class", "items.name"}, {{"ITEMVALUES", each Text.Combine([items.values], ","), type text }}),
    #"Pivoted Column" = Table.Pivot(#"Grouped Rows", List.Distinct(#"Grouped Rows"[items.name]), "items.name", "ITEMVALUES"),
    #"Added Custom" = Table.AddColumn(#"Pivoted Column", "Custom", each Table.RenameColumns(


Table.FromColumns ( { Text.Split([Name], ","),Text.Split([Description], ","),Text.Split([Serial], ",") }),

 {{"Column1", "Name"},{"Column2", "Description"},{"Column3", "Serial"}},
 
 
    MissingField.Ignore
)),
    #"Removed Columns1" = Table.RemoveColumns(#"Added Custom",{"Name", "Description", "Serial"}),
    #"Expanded Custom" = Table.ExpandTableColumn(#"Removed Columns1", "Custom", {"Name", "Description", "Serial"}, {"Name.1", "Description", "Serial"})
in
    #"Expanded Custom"

 

Be aware that if you have more columns you need to keep, then the grouping must be done by all of them.


Regards

Miguel Félix


Did I answer your question? Mark my post as a solution!

Proud to be a Super User!

Check out my blog: Power BI em Português



Thanks that works!

I thought I might have to do something like that but I was hoping there might be a simpler way to handle it. 😊

Helpful resources

Announcements
Microsoft Fabric Learn Together

Microsoft Fabric Learn Together

Covering the world! 9:00-10:30 AM Sydney, 4:00-5:30 PM CET (Paris/Berlin), 7:00-8:30 PM Mexico City

PBI_APRIL_CAROUSEL1

Power BI Monthly Update - April 2024

Check out the April 2024 Power BI update to learn about new features.

April Fabric Community Update

Fabric Community Update - April 2024

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