SPL 查询与报表计算实战指南 - 8 多层 Json 的计算

8 多层Json的计算

这类任务是指对多层次多维度Json串的计算、生成和解析。大部分SQL只支持二维结构的记录集合,必须用函数把多层Json降为二维结构,才能进行计算,如果层级较多,代码将非常繁琐。某些新型SQL能支持Json各层级引用了,但又会引用新的方法和函数,增加代码复杂度。

1把订单和部门合并成的多层Json作为员工表的计算列

数据源:员工表、订单表

目标:在员工表增加Json计算列Sales,由Dept对象和Orders数组组成,Dept取自员工表,Orders取自员工对应的订单记录。

Picture1png
其中某条记录的 Sales 字段值为:

Picture2png

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:根据员工表新建序表,EldName字段是简单数据类型,直接取自原表,Sales字段是多层泛型的数据结构,由一条记录组成,其中, Sales字段的Dept字段取自员工表,Orders字段是订单表的记录集合,通过过滤得到。函数"A1.new"表示根据序表A1创建新序表,函数"new"表示创建一条新记录。

Picture3png

l 知识点:SPL序表适合表达多层数据结构

SPL序表的字段值是泛型的,可以是简单数据类型,也可以是数组、记录、记录集合(序表),还可以多层嵌套,适合表达多层的数据结构。

A3:用函数JsonSPL的多层序表转换成多层Json串。

Picture4png

l 知识点:序表和Json串的互转

多层Json串有两种数据类型,对象和数组,其中,对象对应SPL的单字段值,数组对应SPL的记录集合,两者有着天然的对应关系。SPL提供了名为Json的函数,可以将多层Json串解析成多层序表,也可以反过来将多层序表转换成多层Json串。

Picture5png

2找出指定的员工记录并将多层Json字段解析为二维订单表

数据源:含有多层json字段的员工表(8/OrdersWithJsonField.txt

目标:找出指定的员工记录,解析多层的json字段Sales,分别从第123层取字段值,拼出二维的订单表。

Picture6png

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串。

Picture7png
A2:用 Json 函数将多层的 Json 字段 Sales 解析为 SPL 序表。

Picture8png
A3:根据 Orders 字段新建二维表,用 "." 号访问多层泛型数据,分别取出第 1 层的 Eid、Name,第 2 层的 Dept,第 3 层的 OrderID、Client、Amount、OrderDate 字段。

Picture9png

l 知识点:用"."号访问多层Json

多层Json是树状结构,普通表达形式很难方便地访问到指定节点,但将多层Json解析成SPL序表(多层泛型)之后,就可以使用"."号访问指定节点了。这种方式符合程序员直觉,类似访问对象属性,适合树状结构。

3按不同层级过滤员工表中的订单并分组统计

数据源:含有多层json字段的员工表(8/OrdersWithJsonField.txt

目标:从员工表找出第2层的部门字段是["Sales","HR","R&D"]之一,且第3层的金额字段范围在1000-5000之间的订单,对这些订单按年份和员工分组,统计每组的订单金额和订单数量。

Picture10png

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串会自动解析成多层序表。

Picture11png
A2:找出第 2 层的部门字段是 [“Sales”,“HR”,“R&D”] 之一,且第 3 层的金额字段范围在 1000-5000 之间的订单。A1.(Sales.Orders.select(…)) 表示循环每个员工,按条件查询当前员工的 Sales 字段的 Orders 字段里的订单集合。

Picture12png
A3:用 conj 函数合并各组成员。A2A3 可以合为一句 A1.conj(Sales.Orders.select(…))

Picture13png
A4:分组汇总。

Picture14png

扩展阅读

(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)