【问题标题】:Extract comma-separated values from JSON Records within a List with PowerQuery使用 PowerQuery 从列表中的 JSON 记录中提取逗号分隔值
【发布时间】:2018-03-31 20:13:14
【问题描述】:

作为我为团队创建的工具的一部分,我通过 PowerQuery 连接到内部 Web 服务。

Web 服务返回嵌套的 JSON,我无法将 JSON 数据解析为我要查找的格式。具体来说,我在将列中的记录内容提取到逗号分隔列表时遇到问题。

数据

如您所见,数据包含与特定“种族”(race_id)相关的详细信息。我要关注的是driver_codes 中的信息,这是一个记录列表。记录的数量从 0 到 4 不等,每条记录的结构为id: 50000(50000 可以是任何 5 位数字)。所以它可能是:

id: 10000 id: 20000 id: 30000

根据要求,原始 JSON 的示例 sn-p:

<race>
    <race_id>ABC123445</race_id>
    <begin_time>2018-03-23T00:00:00Z</begin_time>
    <vehicle_id>gokart_11</vehicle_id>
    <driver_code>
        <id>90200</id>
    </driver_code> 
    <driver_code>
        <id>90500</id>
    </driver_code>
</race>

我希望它的结构如下:

10000,20000,30000

问题

当我在包含列表的列上选择“提取值”时,我收到以下消息:

Expression.Error:我们无法将 Record 类型的值转换为类型 文字。

如果我改为选择“扩展到新行”,则会为每个唯一的驱动程序代码创建重复的行。我现在每个唯一的race_id 有几行,但我想要的是每个唯一的race_id 一行和一个串联的驱动程序代码列表。

我的尝试

我已尝试按 race_id 对数据进行分组,但分组数据时允许的操作不包括连接行。

我也尝试过取消透视该列,但这给我留下了同样的问题:我仍然得到多行。

我已经在谷歌上广泛搜索(和 Stack Overflowed)这个问题,但没有运气。但是,可能是我使用了错误的关键字,所以如果存在重复,我深表歉意。

更新:根据目前的答案,我已经尝试过什么

我尝试了 Alexis Olson 的优秀且非常详细的方法,但我最终得到以下错误:

Expression.Error:我们无法将值“id”转换为数字类型。详情:

值=id 类型=类型

错误来自使用这些 M 代码行中的任何一行(一个带有 List.Transform 和一个没有):

= Table.Group(#"Renamed Columns", {"race_id", "begin_time", "vehicle_id"},
 {{"DriverCodes", each Text.Combine([driver_code][id], ","), type text}})
= Table.Group(#"Renamed Columns", {"race_id", "begin_time", "vehicle_id"},
 {{"DriverCodes", each Text.Combine(List.Transform([driver_code][id], each Number.ToText(_)), ","), type text}})

注意:如果我不写[driver_code][id],而只写[id],那么我会收到另一个错误,说[id] 列不存在。

【问题讨论】:

  • 我很难重现您的错误。您能否提供一个您尝试使用的示例 JSON 字符串?
  • 已添加。请看我的编辑。这会让你更清楚吗?
  • 当然。那是 XML,不是 JSON。

标签: json list record powerquery


【解决方案1】:

这是与您提供的 XML 示例等效的 JSON:

{"race": {
    "race_id": "ABC123445",
    "begin_time": "2018-03-23T00:00:00Z",
    "vehicle_id": "gokart_11",
    "driver_code": [
      { "id": "90200" },
      { "id": "90500" }
    ]}}

如果将其加载到查询编辑器中,将其转换为表格,然后展开 Value 记录,您将拥有如下所示的表格:

此时,选择 Expand to New Rows,然后展开 id 列,使您的表格如下所示:

此时,您可以应用@mccard 建议的技巧。按第一列分组并使用最大值聚合最后一列。

这最后一步产生的 M 代码如下:

= Table.Group(#"Expanded driver_code1",
              {"Name", "race_id", "begin_time", "vehicle_id"},
              {{"id", each List.Max([id]), type text}})

您希望将List.Max 替换为Text.Combine,如下所示:

= Table.Group(#"Changed Type",
              {"Name", "race_id", "begin_time", "vehicle_id"},
              {{"id", each Text.Combine([id], ","), type text}})

请注意,如果您的 id 列不是文本格式,那么这将引发错误。要解决此问题,请在使用Transform Tab &gt; Data Type: Text 对行进行分组之前插入一个步骤 以转换类型。另一种选择是在您的Text.Combine 中使用List.Transform,如下所示:

Text.Combine(List.Transform([id], each Number.ToText(_)), ",")

无论哪种方式,你都应该得到这样的结果:

【讨论】:

  • 我已根据您的回答编辑了我的问题以包含结果。你能看看那个吗?您的代码看起来确实是正确的方法,但我仍然收到与之前类似的错误。
  • 您似乎跳过了从driver_code 扩展到id 列的步骤。在进行分组之前,请检查您的表格是否与我的第二张图片相似。
  • 啊。当然。现在我展开了该列,它可以完美运行。我希望我有足够的代表来 +1 你的精彩回答,但你必须接受。非常感谢!
【解决方案2】:

一种方法是使用高级编辑器并在代码中直接将数据分组时更改完成的操作。

首先,使用菜单中可用的操作之一创建分组。例如,使用 Sum 操作创建列“Sum”。它会报错,但我们应该让开始代码继续工作。

然后,打开高级编辑器,找到操作对应的代码。它应该是这样的:

{{“Sum”,每个 List.Sum([driver_codes]),输入文本}}

改成:

{{"driver_codes", 每个Text.Combine([driver_codes], ","), type text}}

【讨论】:

  • 感谢您查看此内容。我尝试了您的解决方案,但出现错误“Expression.Error:我们无法将 List 类型的值转换为 Text 类型。详细信息:Value=List Type=Type”。也许它与 JSON 的结构有关。我将其添加到我的问题中。你能看一下它是否有什么不同吗?
  • 看来亚历克西斯·奥尔森在他的最后指示中已经解决了这个新问题。
猜你喜欢
  • 2011-05-26
  • 1970-01-01
  • 2013-03-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-24
  • 2013-02-23
  • 1970-01-01
相关资源
最近更新 更多