SPL 查询与报表计算实战指南 - 8 多层 Json 的计算
8 多层Json的计算
这类任务是指对多层次多维度Json串的计算、生成和解析。大部分SQL只支持二维结构的记录集合,必须用函数把多层Json降为二维结构,才能进行计算,如果层级较多,代码将非常繁琐。某些新型SQL能支持Json各层级引用了,但又会引用新的方法和函数,增加代码复杂度。
例1:把订单和部门合并成的多层Json作为员工表的计算列
数据源:员工表、订单表
目标:在员工表增加Json计算列Sales,由Dept对象和Orders数组组成,Dept取自员工表,Orders取自员工对应的订单记录。
其中某条记录的 Sales 字段值为:
SPL代码:
A |
B |
|
1 |
$select EId,Dept,Name from Employee.txt |
$select * from Orders.txt |
2 |
=A1.new(EId,Name,new(Dept,B1.select(SellerId==EId):Orders):Sales) |
|
3 |
=A2.run(Sales=json(Sales)) |
A1A2:加载数据。
A2:根据员工表新建序表,Eld和Name字段是简单数据类型,直接取自原表,Sales字段是多层泛型的数据结构,由一条记录组成,其中, Sales字段的Dept字段取自员工表,Orders字段是订单表的记录集合,通过过滤得到。函数"A1.new"表示根据序表A1创建新序表,函数"new"表示创建一条新记录。
l 知识点:SPL序表适合表达多层数据结构
SPL序表的字段值是泛型的,可以是简单数据类型,也可以是数组、记录、记录集合(序表),还可以多层嵌套,适合表达多层的数据结构。
A3:用函数Json把SPL的多层序表转换成多层Json串。
l 知识点:序表和Json串的互转
多层Json串有两种数据类型,对象和数组,其中,对象对应SPL的单字段值,数组对应SPL的记录集合,两者有着天然的对应关系。SPL提供了名为Json的函数,可以将多层Json串解析成多层序表,也可以反过来将多层序表转换成多层Json串。
例2:找出指定的员工记录并将多层Json字段解析为二维订单表
数据源:含有多层json字段的员工表(8/OrdersWithJsonField.txt)
目标:找出指定的员工记录,解析多层的json字段Sales,分别从第1、2、3层取字段值,拼出二维的订单表。
SPL代码:
A |
|
1 |
$select * from {file("8/OrdersWithJsonField.txt").import@tf()} where EId='7' |
2 |
=A1.run(Sales=json(Sales)) |
3 |
=A2.Sales.Orders.new(A1.EId,A1.Name,A1.Sales.Dept,OrderID,Client,Amount,OrderDate) |
A1:加载数据,查询指定的员工记录。直接加载文本文件数据时,SPL会自动解析Json串,加载数据库数据时不解析,为了模拟真实场景,这里使用函数import,@f表示只取字符串,不自动解析,包括Json串。
A2:用 Json 函数将多层的 Json 字段 Sales 解析为 SPL 序表。
A3:根据 Orders 字段新建二维表,用 "." 号访问多层泛型数据,分别取出第 1 层的 Eid、Name,第 2 层的 Dept,第 3 层的 OrderID、Client、Amount、OrderDate 字段。
l 知识点:用"."号访问多层Json
多层Json是树状结构,普通表达形式很难方便地访问到指定节点,但将多层Json解析成SPL序表(多层泛型)之后,就可以使用"."号访问指定节点了。这种方式符合程序员直觉,类似访问对象属性,适合树状结构。
例3:按不同层级过滤员工表中的订单并分组统计
数据源:含有多层json字段的员工表(8/OrdersWithJsonField.txt)
目标:从员工表找出第2层的部门字段是["Sales","HR","R&D"]之一,且第3层的金额字段范围在1000-5000之间的订单,对这些订单按年份和员工分组,统计每组的订单金额和订单数量。
SPL代码:
A |
|
1 |
$select * from 8/OrdersWithJsonField.txt |
2 |
=A1.(Sales.Orders.select( ["Sales","HR","R&D"].contain(Sales.Dept) && Amount>2000 && Amount<=5000 )) |
3 |
=A2.conj() |
4 |
=A3.groups(year(OrderDate):y,SellerId;sum(Amount):amt,count(1):cnt) |
A1:加载数据,文本文件中的Json串会自动解析成多层序表。
A2:找出第 2 层的部门字段是 [“Sales”,“HR”,“R&D”] 之一,且第 3 层的金额字段范围在 1000-5000 之间的订单。A1.(Sales.Orders.select(…)) 表示循环每个员工,按条件查询当前员工的 Sales 字段的 Orders 字段里的订单集合。
A3:用 conj 函数合并各组成员。A2A3 可以合为一句 A1.conj(Sales.Orders.select(…))
A4:分组汇总。
扩展阅读
(https://c.raqsoft.com.cn/article/1742978127225)
(https://c.raqsoft.com.cn/article/1724038939133)
(https://c.raqsoft.com.cn/article/1745897461849)
(https://c.raqsoft.com.cn/article/1742565223821)