在 postgres 查询中执行 "running json concatenation"

Do a "running json concatenation" in postgres query

是否可以为 json 做类似于 运行 求和的事情?

我有这个table:

   day        id          data
────────────┼───────┼───────────────────
 2016-06-20 │     1 │ {"key0": "value0"}
 2016-06-21 │     1 │ {"key1": "value1"}
 2016-06-22 │     1 │ {"key2": "value2"}

我希望它是这样的 table:

   day        id                  data
────────────┼───────┼────────────────────────────────────────────────────
 2016-06-20 │     1 │ {"key0": "value0"}
 2016-06-21 │     1 │ {"key0": "value0", "key1": "value1"}
 2016-06-22 │     1 │ {"key0": "value0", "key1": "value1", "key2": "value2"}

我尝试使用 window 函数,因为聚合函数的默认行为与此类似,但我不知道如何为 json.

正确执行此操作

有人能帮忙吗?

只要您有办法定义每行的 "combined" 数据中应包含哪些其他行,就可以直接使用 LATERAL.

testdb=# create table t(day date, id bigint, data jsonb);
ERROR:  relation "t" already exists
testdb=# select * from t;
    day     | id |        data        
------------+----+--------------------
 2016-06-20 |  1 | {"key0": "value0"}
 2016-06-21 |  1 | {"key1": "value1"}
 2016-06-22 |  1 | {"key2": "value2"}
(3 rows)

testdb=# SELECT t0.day,                                  
       t0.id,
       j
FROM t t0, LATERAL
(SELECT jsonb_object(keys, vals) j
 FROM (SELECT array_agg(kvset.key) keys,
              array_agg(kvset.value) vals
       FROM
   (SELECT key, value FROM t t1
    CROSS JOIN jsonb_each_text(t1.data) AS r
    WHERE t1.day<=t0.day) AS kvset
    ) AS kvpairs
)_;
    day     | id |                           j                            
------------+----+--------------------------------------------------------
 2016-06-20 |  1 | {"key0": "value0"}
 2016-06-21 |  1 | {"key0": "value0", "key1": "value1"}
 2016-06-22 |  1 | {"key0": "value0", "key1": "value1", "key2": "value2"}

在这种情况下,我使用 t1.day<=t0.day 来指示应扫描等于或小于给定日期的所有行,以便为该日期的行构建组合对象。

值得注意的是,我没有做任何事情来巧妙地处理冲突的键;当它在多行中遇到相同的键时,这可能不会做正确的事情。

没有连接 JSONB 个对象的内置聚合(jsonb_agg() returns 一个数组,而不是单个 JSON 值),但这真的很容易创建一个:

create aggregate jsonb_append(jsonb) 
(
    sfunc = jsonb_concat(jsonb, jsonb),
    stype = jsonb
);

此聚合也可以用作 window function,它执行 "running aggregate",因此您可以:

select day, id, jsonb_append(data) over (order by day)
from topo
order by day;

请注意 JSONB 不保留键的顺序。因此,聚合 jsonb 值中键的顺序可能与检索顺序不完全相同。

如果相同的键存在于多行中,"last"行的值(根据order by)将被保留。

Online example