2017-05-25 30 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'? –