USQL创建JSON数据表问题:提取嵌套结构的行属性值
解决USQL中提取嵌套Name-Value结构JSON并创建数据表的问题
我明白你现在的痛点:手里的JSON是数组格式,每行数据的属性都嵌套成{Name: "XXX", Value: "YYY"}的结构,没法直接像普通JSON那样用row[3].property4获取指定行的属性值,而且之前尝试建表还报错了。下面我一步步给你拆解解决方案:
先明确你的JSON结构(示例)
首先假设你的JSON长这样(和你描述的结构匹配):
[ { "Attributes": [ {"Name": "property1", "Value": "row1_val1"}, {"Name": "property2", "Value": "row1_val2"}, {"Name": "property4", "Value": "row1_val4"} ] }, { "Attributes": [ {"Name": "property1", "Value": "row2_val1"}, {"Name": "property2", "Value": "row2_val2"}, {"Name": "property4", "Value": "row2_val4"} ] }, { "Attributes": [ {"Name": "property1", "Value": "row3_val1"}, {"Name": "property2", "Value": "row3_val2"}, {"Name": "property4", "Value": "row3_val4"} ] } ]
顶层是数组,每个元素代表一行数据,每行的属性都存在Attributes数组里,每个属性都是Name-Value的嵌套对象。
第一步:解析JSON并展开嵌套结构
我们先用OPENJSON读取整个JSON数组,再用CROSS APPLY+EXPLODE把每行的Name-Value对拆成单独的行记录:
SELECT -- 生成行号,对应你要的row[3](注意USQL里行号从1开始) ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS row_num, prop.Name, prop.Value FROM -- 读取你的JSON文件路径 OPENJSON(@"/your/storage/path/data.json") -- 定义每行的结构:Attributes是一个对象数组 WITH (Attributes ARRAY<OBJECT> '$') AS raw_rows -- 展开每行的Attributes数组,得到每个Name-Value对 CROSS APPLY EXPLODE(raw_rows.Attributes) AS prop;
执行这个查询后,你会得到这样的结果:
| row_num | Name | Value |
|---|---|---|
| 1 | property1 | row1_val1 |
| 1 | property2 | row1_val2 |
| 1 | property4 | row1_val4 |
| 2 | property1 | row2_val1 |
| ... | ... | ... |
第二步:转成宽表(实现row[3].property4的访问方式)
接下来用PIVOT把Name转成列名,Value作为对应列的值,这样就能像普通数据表一样访问指定行的属性了:
SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS row_num, prop.Name, prop.Value FROM OPENJSON(@"/your/storage/path/data.json") WITH (Attributes ARRAY<OBJECT> '$') AS raw_rows CROSS APPLY EXPLODE(raw_rows.Attributes) AS prop ) AS src -- 把需要的属性名列出来,转成表的列 PIVOT ( MAX(Value) FOR Name IN (property1, property2, property4) ) AS pivoted_table;
这时候结果就是标准的宽表:
| row_num | property1 | property2 | property4 |
|---|---|---|---|
| 1 | row1_val1 | row1_val2 | row1_val4 |
| 2 | row2_val1 | row2_val2 | row2_val4 |
| 3 | row3_val1 | row3_val2 | row3_val4 |
现在你要获取第三行的property4值,直接用WHERE row_num = 3就能拿到row3_val4,完美匹配你想要的row[3].property4效果。
第三步:创建并填充数据表
如果要把这个结果持久化到USQL表中,直接用CREATE TABLE+INSERT INTO组合即可:
-- 创建目标表,根据你的属性类型调整字段类型 CREATE TABLE IF NOT EXISTS ProcessedData ( row_num INT, property1 STRING, property2 STRING, property4 STRING ); -- 把解析后的数据插入到目标表 INSERT INTO ProcessedData SELECT * FROM ( SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS row_num, prop.Name, prop.Value FROM OPENJSON(@"/your/storage/path/data.json") WITH (Attributes ARRAY<OBJECT> '$') AS raw_rows CROSS APPLY EXPLODE(raw_rows.Attributes) AS prop ) AS src PIVOT ( MAX(Value) FOR Name IN (property1, property2, property4) ) AS pivoted_table;
常见报错排查
如果之前建表报错,大概率是这几个原因:
- JSON格式错误:USQL对JSON的语法要求严格,必须用双引号,不能有多余的逗号,确保你的JSON是标准格式。
- 类型不匹配:如果
Value有多种数据类型(比如数字、字符串混合),统一用STRING类型来兼容,或者在WITH子句里指定对应类型(比如Value INT '$.Value')。 - 行顺序不稳定:如果需要固定的行顺序,最好用数据里自带的唯一标识字段来排序,替换掉
ORDER BY (SELECT NULL)。
内容的提问来源于stack exchange,提问作者david nadal
相关产品推荐
相关产品推荐

