PowerQuery M语言-展开类型为“记录列表的记录列表”的列

问题描述

我正在使用Excel Powerquery(M语言)来访问SNOMED CT服务器的RESTful API。服务器返回的JSON是一个深层嵌套的结构。

下面的示例被过滤以显示单个项目,通常items数组将包含多个结果。

示例-

{
  "items": [
    {
      "id": "258674000","released": true,"active": true,"effectiveTime": "20020131","moduleId": "900000000000207008","iconId": "362981000","definitionStatus": {
        "id": "900000000000074008"
      },"subclassDefinitionStatus": "NON_DISJOINT_SUBCLASSES","fsn": {
        "id": "3508354011","term": "Micrometer (qualifier value)","concept": {
          "id": "258674000"
        },"type": {
          "id": "900000000000003001"
        },"typeId": "900000000000003001","conceptId": "258674000","acceptability": {
          "900000000000509007": "PREFERRED","900000000000508004": "PREFERRED"
        }
      },"pt": {
        "id": "384891018","term": "um","type": {
          "id": "900000000000013009"
        },"typeId": "900000000000013009","descriptions": {
        "items": [
          {
            "id": "2609609012","active": false,"effectiveTime": "20170731","iconId": "900000000000003001","term": "micrometer (qualifier value)","semanticTag": "qualifier value","languageCode": "en","caseSignificance": {
              "id": "900000000000448009"
            },"concept": {
              "id": "258674000"
            },"type": {
              "id": "900000000000003001"
            },"caseSignificanceId": "900000000000448009","acceptability": {}
          },{
            "id": "384891018","iconId": "900000000000013009","semanticTag": "","caseSignificance": {
              "id": "900000000000017005"
            },"type": {
              "id": "900000000000013009"
            },"caseSignificanceId": "900000000000017005","acceptability": {
              "900000000000509007": "PREFERRED","900000000000508004": "PREFERRED"
            }
          },{
            "id": "650119013","effectiveTime": "20060731","term": "um (qualifier value)",{
            "id": "384888018","term": "micrometer",{
            "id": "3508354011",{
            "id": "3508411019","term": "Micrometer","acceptability": {
              "900000000000509007": "ACCEPTABLE"
            }
          },{
            "id": "384889014","term": "micrometre","acceptability": {
              "900000000000508004": "ACCEPTABLE"
            }
          },{
            "id": "384890017","term": "micron","acceptability": {
              "900000000000509007": "ACCEPTABLE","900000000000508004": "ACCEPTABLE"
            }
          }
        ],"limit": 8,"total": 8
      },"ancestorIds": [
        "-1","138875005","258667005","362981000","767524001"
      ],"parentIds": [
        "258668000"
      ],"statedAncestorIds": [
        "-1","statedParentIds": [
        "258668000"
      ],"definitionStatusId": "900000000000074008"
    }
  ],"searchAfter": "AoE_BTAxMzRlZWNhLTYxODEtNDFjYi1hNmJlLWQzN2IwMGFlYzEyNA==","limit": 50,"total": 1
}

JSON中的顶级对象表示M语言术语的记录列表。使用查询服务器的自定义函数fromServer(endpoint),我可以使用-

扩展JSON结果
let
    concepts = Table.FromRecords(fromServer("API_ENDPOINT")[items]),in
    concepts

这给了我一张概念表,每行一个。但是我被困在下一点。

每个概念都有一组可能的同义词。这些是SNOMED术语的描述。上述表格中的descriptions列是“记录”列,其中每个记录都有一个字段itemsitems是记录的列表,并且记录包含要访问的键/值对。我想做的是展开descriptions列,按名称展开选定的值,或展开最底层“记录”中的所有值。

因此,这类似于Table.ExpandTableColumn(),其中要扩展的值来自形状列-

descriptions (the column name)
  Records
    items: List
      Records
        Keys : Values

我必须承认,我不确定该如何着手,逐步进入表字段中的嵌套结构化值,然后累积结果。任何指针将不胜感激。

解决方法

如果我正确理解了您的问题,则认为您正在采取以下措施:

let
    json = "{""items"":[{""id"":""258674000"",""released"":true,""active"":true,""effectiveTime"":""20020131"",""moduleId"":""900000000000207008"",""iconId"":""362981000"",""definitionStatus"":{""id"":""900000000000074008""},""subclassDefinitionStatus"":""NON_DISJOINT_SUBCLASSES"",""fsn"":{""id"":""3508354011"",""term"":""Micrometer (qualifier value)"",""concept"":{""id"":""258674000""},""type"":{""id"":""900000000000003001""},""typeId"":""900000000000003001"",""conceptId"":""258674000"",""acceptability"":{""900000000000509007"":""PREFERRED"",""900000000000508004"":""PREFERRED""}},""pt"":{""id"":""384891018"",""term"":""um"",""type"":{""id"":""900000000000013009""},""typeId"":""900000000000013009"",""descriptions"":{""items"":[{""id"":""2609609012"",""active"":false,""effectiveTime"":""20170731"",""iconId"":""900000000000003001"",""term"":""micrometer (qualifier value)"",""semanticTag"":""qualifier value"",""languageCode"":""en"",""caseSignificance"":{""id"":""900000000000448009""},""caseSignificanceId"":""900000000000448009"",""acceptability"":{}},{""id"":""384891018"",""iconId"":""900000000000013009"",""semanticTag"":"""",""caseSignificance"":{""id"":""900000000000017005""},""caseSignificanceId"":""900000000000017005"",{""id"":""650119013"",""effectiveTime"":""20060731"",""term"":""um (qualifier value)"",{""id"":""384888018"",""term"":""micrometer"",{""id"":""3508354011"",{""id"":""3508411019"",""term"":""Micrometer"",""acceptability"":{""900000000000509007"":""ACCEPTABLE""}},{""id"":""384889014"",""term"":""micrometre"",""acceptability"":{""900000000000508004"":""ACCEPTABLE""}},{""id"":""384890017"",""term"":""micron"",""acceptability"":{""900000000000509007"":""ACCEPTABLE"",""900000000000508004"":""ACCEPTABLE""}}],""limit"":8,""total"":8},""ancestorIds"":[""-1"",""138875005"",""258667005"",""362981000"",""767524001""],""parentIds"":[""258668000""],""statedAncestorIds"":[""-1"",""statedParentIds"":[""258668000""],""definitionStatusId"":""900000000000074008""}],""searchAfter"":""AoE_BTAxMzRlZWNhLTYxODEtNDFjYi1hNmJlLWQzN2IwMGFlYzEyNA=="",""limit"":50,""total"":1}",parsed = Json.Document(json),toTable = Table.FromRecords(parsed[items]),flattenedDescriptions = Table.TransformColumns(toTable,{"descriptions",each Table.FromRecords([items]),type table}),// If the columns you want to expand are fixed/constant,you can hard code them. Something like this.
    expandHardCoded = Table.ExpandTableColumn(flattenedDescriptions,"descriptions",{"id","released","active","effectiveTime","moduleId","iconId","term","semanticTag","languageCode","caseSignificance","concept","type","typeId","conceptId","caseSignificanceId","acceptability"},{"id.1","released.1","active.1","effectiveTime.1","moduleId.1","iconId.1","acceptability"}),// If the columns you want to expand need to be determined dynamically but every table will have the same column names,then can look at first table and use its column names when expanding.
    expandBasedOnFirstRowOnly = 
        let
            columnsToExpand = Table.ColumnNames(flattenedDescriptions{0}[descriptions]),renamed = List.Transform(columnsToExpand,each "descriptions." & _),expanded = Table.ExpandTableColumn(flattenedDescriptions,columnsToExpand,renamed)
        in expanded,// If the columns you want to expand need to be determined dynamically but every table will not have the same column names,then create an exhaustive,unique list. This goes through every row in the table though,so might be a little slower.
    expandBasedOnAllRows =
        let
            columnsToExpand = List.Distinct(List.Combine(List.Transform(flattenedDescriptions[descriptions],Table.ColumnNames))),renamed)
        in expanded
in
    expandBasedOnAllRows
  • Table.TransformColumns将遍历descriptions列中的每个值,并将每个值的items字段转换为表格-然后可以对其进行扩展。
  • expandHardCodedexpandBasedOnFirstRowOnlyexpandBasedOnAllRows步骤只是扩展嵌套列的三种不同方法。根据您要处理的数据的性质,(n)您可能不适合使用这些方法中的一种。

相关问答

依赖报错 idea导入项目后依赖报错,解决方案:https://blog....
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下...
错误1:gradle项目控制台输出为乱码 # 解决方案:https://bl...
错误还原:在查询的过程中,传入的workType为0时,该条件不起...
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct...