Power BI:将来自无序 JSON 对象的查找值放在正确的列中
Power BI: place lookup values from disordered JSON objects in correct columns
在 Power BI 中,我有一列包含 JSON。每行包含 3 key:value 对,格式为 3 位:4 位,如下例
Table 1
{"567":"1259","568":"1535","570":"1264"}
{"393":"9521","392":"5351","394":"4621"}
每个 key:value 都可用于在另一个 table 中查找条目:
Table 2
Key | Value | Entry
-------------------
567 | 1259 | Apple
568 | 1535 | Large
570 | 1264 | Red
393 | 9521 | Small
392 | 5351 | Pear
394 | 4621 | Green
我想创建 3 个新列以附加到 Table 1,填充了从 table 2 中查找的条目,如下所示:
Fruit | Size | Colour
----------------------
Apple | Large | Red
Pear | Small | Green
我的首选解决方案是 split
JSON 列用 ,
分隔符变成 3,然后 merge
用 Table 2通过 Key
。但是,由于 JSON 对象未排序,因此第 1 列中的第一个键可能表示水果,而第 2 列中的第一个键可能表示大小。在此插图中,这将导致水果列中的大小值,这不是本意:
Fruit | Size | Colour
----------------------
Apple | Large | Red
Small | Pear | Green
值得庆幸的是,键 value 的 order 及其在我的 table 中所代表的内容具有一致的模式2 数据。换句话说,具有最低值的键代表水果,具有次高值的键代表大小,具有最高值的键代表颜色。
因此,我认为一个解决方案可能是在 Power BI 中找到一种方法,以编程方式获取 JSON 列并通过升序键值对 JSON 内容进行排序。
示例输入:
{"393":"1259","392":"1535","394":"1264"}
期望输出:
{"392": "1535","393":"1259","394": "1264"}
正如其他人指出的那样,这可能不是解决此问题的最佳方法,因此我愿意接受建议。
我也知道这是由于数据库设计不佳造成的,但我就是这样!
感谢mahoneypat who answered this question on the Power BI community forum。我可以确认它有效。
我把他的回答贴在下面,这样 Whosebug 上的任何人都可以:
Here's one way to do it in the query editor. To see how it works, just create a blank query, open the Advanced Editor and replace the text there with the M code below.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("NcvLEYAgDEXRXt6aheSHsRVCJY69C0G3Z+7tHXdArQWuQCX1QFlwblDWDe34CpPAg1FyZOdkV6rZsVPC/H6QBLFVzHG8", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [JsonData = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"JsonData", type text}}),
#"Added Custom1" = Table.AddColumn(#"Changed Type", "Result", each let
thisrecord = Json.Document([JsonData]),
sortedrecord = Record.ReorderFields(thisrecord, List.Sort(Record.FieldNames(thisrecord))),
renamedrecord = Record.RenameFields(sortedrecord, List.Zip({Record.FieldNames(sortedrecord), {"Fruit", "Size", "Color"}}))
in
renamedrecord),
#"Expanded Result" = Table.ExpandRecordColumn(#"Added Custom1", "Result", {"Fruit", "Size", "Color"}, {"Fruit", "Size", "Color"})
in
#"Expanded Result"
The key step is the custom column with this expression. Replace [JsonData] with your actual column name with the Json string.
let
thisrecord = Json.Document([JsonData]),
sortedrecord = Record.ReorderFields(thisrecord, List.Sort(Record.FieldNames(thisrecord))),
renamedrecord = Record.RenameFields(sortedrecord, List.Zip({Record.FieldNames(sortedrecord), {"Fruit", "Size", "Color"}}))
in
renamedrecord
在 Power BI 中,我有一列包含 JSON。每行包含 3 key:value 对,格式为 3 位:4 位,如下例
Table 1
{"567":"1259","568":"1535","570":"1264"}
{"393":"9521","392":"5351","394":"4621"}
每个 key:value 都可用于在另一个 table 中查找条目:
Table 2
Key | Value | Entry
-------------------
567 | 1259 | Apple
568 | 1535 | Large
570 | 1264 | Red
393 | 9521 | Small
392 | 5351 | Pear
394 | 4621 | Green
我想创建 3 个新列以附加到 Table 1,填充了从 table 2 中查找的条目,如下所示:
Fruit | Size | Colour
----------------------
Apple | Large | Red
Pear | Small | Green
我的首选解决方案是 split
JSON 列用 ,
分隔符变成 3,然后 merge
用 Table 2通过 Key
。但是,由于 JSON 对象未排序,因此第 1 列中的第一个键可能表示水果,而第 2 列中的第一个键可能表示大小。在此插图中,这将导致水果列中的大小值,这不是本意:
Fruit | Size | Colour
----------------------
Apple | Large | Red
Small | Pear | Green
值得庆幸的是,键 value 的 order 及其在我的 table 中所代表的内容具有一致的模式2 数据。换句话说,具有最低值的键代表水果,具有次高值的键代表大小,具有最高值的键代表颜色。
因此,我认为一个解决方案可能是在 Power BI 中找到一种方法,以编程方式获取 JSON 列并通过升序键值对 JSON 内容进行排序。
示例输入:
{"393":"1259","392":"1535","394":"1264"}
期望输出:
{"392": "1535","393":"1259","394": "1264"}
正如其他人指出的那样,这可能不是解决此问题的最佳方法,因此我愿意接受建议。
我也知道这是由于数据库设计不佳造成的,但我就是这样!
感谢mahoneypat who answered this question on the Power BI community forum。我可以确认它有效。
我把他的回答贴在下面,这样 Whosebug 上的任何人都可以:
Here's one way to do it in the query editor. To see how it works, just create a blank query, open the Advanced Editor and replace the text there with the M code below.
let
Source = Table.FromRows(Json.Document(Binary.Decompress(Binary.FromText("NcvLEYAgDEXRXt6aheSHsRVCJY69C0G3Z+7tHXdArQWuQCX1QFlwblDWDe34CpPAg1FyZOdkV6rZsVPC/H6QBLFVzHG8", BinaryEncoding.Base64), Compression.Deflate)), let _t = ((type nullable text) meta [Serialized.Text = true]) in type table [JsonData = _t]),
#"Changed Type" = Table.TransformColumnTypes(Source,{{"JsonData", type text}}),
#"Added Custom1" = Table.AddColumn(#"Changed Type", "Result", each let
thisrecord = Json.Document([JsonData]),
sortedrecord = Record.ReorderFields(thisrecord, List.Sort(Record.FieldNames(thisrecord))),
renamedrecord = Record.RenameFields(sortedrecord, List.Zip({Record.FieldNames(sortedrecord), {"Fruit", "Size", "Color"}}))
in
renamedrecord),
#"Expanded Result" = Table.ExpandRecordColumn(#"Added Custom1", "Result", {"Fruit", "Size", "Color"}, {"Fruit", "Size", "Color"})
in
#"Expanded Result"
The key step is the custom column with this expression. Replace [JsonData] with your actual column name with the Json string.
let
thisrecord = Json.Document([JsonData]),
sortedrecord = Record.ReorderFields(thisrecord, List.Sort(Record.FieldNames(thisrecord))),
renamedrecord = Record.RenameFields(sortedrecord, List.Zip({Record.FieldNames(sortedrecord), {"Fruit", "Size", "Color"}}))
in
renamedrecord