如何在PostgreSQL中聚合具有可变键数的JSON数组?
我在PostgreSQL表中有一系列行,如下所示:如何在PostgreSQL中聚合具有可变键数的JSON数组?,sql,json,postgresql,aggregate-functions,postgresql-9.5,Sql,Json,Postgresql,Aggregate Functions,Postgresql 9.5,我在PostgreSQL表中有一系列行,如下所示: -[ RECORD 1 ]--------------------------------------------------------------------- student | e04c0ae4709340cb8e03c52f444e723f group | 1 subgroup | 1 variable | VAR1 status | { "track_A" : "Done", "track_
-[ RECORD 1 ]---------------------------------------------------------------------
student | e04c0ae4709340cb8e03c52f444e723f
group | 1
subgroup | 1
variable | VAR1
status | { "track_A" : "Done", "track_B" : "Done", "track_C" : "To Do" }
-[ RECORD 2 ]---------------------------------------------------------------------
student | e04c0ae4709340cb8e03c52f444e723f
group | 1
subgroup | 1
variable | VAR2
status | { "track_A" : "To Do", "track_B" : "Done", "track_C" : "To Do" }
-[ RECORD 3 ]---------------------------------------------------------------------
student | 849d1e6a0c2b4530a2b550829df94556
group | 0
subgroup | 1
variable | VAR3
status | { "track_A" : "Done", "track_B" : "To Do", "track_C" : "To Do" }
我想按学生、组和子组对它们进行分组,并获得每个曲目的计数状态。比如:
-[ RECORD 1 ]---------------------------------------------------------------------
student | e04c0ae4709340cb8e03c52f444e723f
group | 1
subgroup | 1
totals | { "track_A" : {"done": 1, "to_do": 1}, {"track_B" : {"done": 0, "to_do": 2}, "track_C" : {"done": 0, "to_do": 2} }
问题是轨道的数量可能会有所不同。我知道它们的名字,但它们不是静态的,所以我无法进行简单的聚合。有什么建议我可以在PostgreSQL(9.5)中写这篇文章吗?我不想对所有轨迹进行迭代和聚合,因为操作需要一些时间。您可以使用“取消测试”值并再次组合它
数据:
查询:
WITH cte AS
(
SELECT student, "group", subgroup, k
,COUNT(CASE WHEN v='Done' THEN 1 END) AS Done
,COUNT(CASE WHEN v='To Do' THEN 1 END) AS To_do
FROM tab
,LATERAL json_each_text(status) s(k,v)
GROUP BY student, "group", subgroup, k
), cte2 AS
(
SELECT student, "group", subgroup, k, json_object_agg(s.status, s.cnt) AS j
FROM cte
,LATERAL (VALUES('Done', Done),('To Do', To_Do)) AS s(status, cnt)
GROUP BY student, "group", subgroup, k
)
SELECT student, "group", subgroup
,json_object_agg(k, j) AS totals
FROM cte2
GROUP BY student, "group", subgroup;
输出:
WITH cte AS
(
SELECT student, "group", subgroup, k
,COUNT(CASE WHEN v='Done' THEN 1 END) AS Done
,COUNT(CASE WHEN v='To Do' THEN 1 END) AS To_do
FROM tab
,LATERAL json_each_text(status) s(k,v)
GROUP BY student, "group", subgroup, k
), cte2 AS
(
SELECT student, "group", subgroup, k, json_object_agg(s.status, s.cnt) AS j
FROM cte
,LATERAL (VALUES('Done', Done),('To Do', To_Do)) AS s(status, cnt)
GROUP BY student, "group", subgroup, k
)
SELECT student, "group", subgroup
,json_object_agg(k, j) AS totals
FROM cte2
GROUP BY student, "group", subgroup;