从 SQL 到 SPL:summarize row counts by dynamic columns into json

数据库表 _temp_data 的每个列可以看作一个数组,数组成员有重复:

hobbies_1

hobbies_2

A

E

B

F

A

A

A

F

现在要对每一列分别进行分组计数,写成 json 格式:

hobbies_1

hobbies_2

{"A":3,"B":1}

{"A":1,"E":1,"F":2}

SQL:

With Grouped AS (
    SELECT
      td.hobbies_1,
      td.hobbies_2,
      COUNT(*) AS count
    FROM _temp_data td
    GROUP BY GROUPING SETS (
      (td.hobbies_1),
      (td.hobbies_2)
    )
)
SELECT
  jsonb_object_agg(g.hobbies_1, g.count) FILTER (WHERE g.hobbies_1 IS NOT NULL) AS hobbies_1,
  jsonb_object_agg(g.hobbies_2, g.count) FILTER (WHERE g.hobbies_2 IS NOT NULL) AS hobbies_2
FROM Grouped g;

SQL先用 GROUPING SETS 对不同的列同时进行分组计数,再用 jsonb_object_agg 分别将每个记录集转为 json,代码比较繁琐;而且必须写出列名,灵活性较差;如果想支持动态列名,就要用存储过程,结构将变得复杂。SPL 不必写出列名:https://try.esproc.com/splx?3mF


 A

1

$select * from _temp_data.txt

2

=E@bp(A1).(json(E@p(E@b(~.groups(~;count(~))))(1)))

3

=A1.create().record(A2)

A1:加载数据。

A2:将二维表 A1 转置为序列的序列,对每个小序列(对应每列)进行分组计数,再转换成 Json。函数 E 用于转换序列和序表,@p 表示二层序列转置,@b 表示去掉列名。记录集合转 Json 时比记录多了 [] 符号,这里用 (1) 取唯一的记录再转。

A3:按 A1 结构新建空二维表,填入 Json 序列 A2。

问题来源:https://stackoverflow.com/questions/78184303/how-to-transform-and-summarize-row-counts