2017-05-25 32 views
2

我想知道是否有聚集的 几行的JSONB列的任何有效的方法,可以考虑此表结构:如何在postgres中聚合jsonb元素的行?

PERFORMANCE(user_id INTEGER, stat_date DATE, metrics JSONB) 

随着行是这样的:

1, 2017-01-01, {"speed":10, "distance":120, "time":5} 
1, 2017-01-02, {"speed":15, "distance":150, "time":8} 
1, 2017-01-03, {"speed":9, "distance":90} 
2, 2017-01-01, {"speed":15, "distance":150, "time":8} 

我想按照user_id的“度量”列内的每个关键字汇总,因此输出如下所示:

1, {"speed":34, "distance":360, "time":13} 
2, {"speed":15, "distance":150, "time":8} 

一个选项是我们e jsonb_each但是会爆炸这一列,我想知道是否有更好的选择。

编辑:重要的是要注意,我不知道JSONB列中的每个键,所以我不能明确地聚合它们。

感谢

回答

4

的一个方法是让他们使用group by user_id从jsonb数据,总和值,然后再次进行jsonb数据:

select user_id, jsonb_build_object('speed', sum((metrics->>'speed')::numeric), 'distance', sum((metrics->>'distance')::numeric) , 'time', sum((metrics->>'time')::numeric)) 
from t 
group by user_id 

编辑

那么,在这种情况下,我觉得作为你说,你可以使用jsonb_each函数(也许还有更好的方法,但我现在看不到它)。我用jsonb_each_text在这里,我不知道你是什么意思but that will explode the column,你可以使用jsonb_object_agg为“建设” jsonb再次反对,这样的事情:

with your_table(user_id , stat_date , metrics) as(
    select 1, '2017-01-01'::date, '{"speed":10, "distance":120, "time":5}'::jsonb union all 
    select 1, '2017-01-02'::date, '{"speed":15, "distance":150, "time":8}'::jsonb union all 
    select 1, '2017-01-02'::date, '{"bla":8}'::jsonb union all 
    select 4, '2017-01-02'::date, '{"bla":8}'::jsonb union all 
    select 1, '2017-01-03'::date, '{"speed":9, "distance":90}'::jsonb union all 
    select 2, '2017-01-01'::date, '{"speed":15, "distance":150, "time":8}'::jsonb 
) 

select user_id, jsonb_object_agg(k, val) from (
    select user_id, k, sum(v::numeric) as val from your_table join lateral jsonb_each_text(metrics) j(k,v) on true 
    group by user_id, k 
) tt 
group by user_id 
+0

这就是我怀疑,但我不知道所有的JSONB列中可能存在的值。 – crorella

+0

你是什么意思?对不起,我不明白这个,你能解释一下吗? –

+0

你的意思是你不知道JSONB中所有可能的'keys'? –