我有一张这样的变更表
CREATE TABLE IF NOT EXISTS changes (
entity_id TEXT NOT NULL,
column_id TEXT NOT NULL,
value JSONB NOT NULL,
updated_at TIMESTAMP NOT NULL
);
INSERT INTO changes VALUES ('1', 'height', to_jsonb(140), '01-01-2021 00:00:00'::TIMESTAMP);
INSERT INTO changes VALUES ('1', 'weight', to_jsonb(30), '01-01-2021 00:00:00'::TIMESTAMP);
INSERT INTO changes VALUES ('1', 'height', to_jsonb(145), '01-02-2021 00:00:00'::TIMESTAMP);
INSERT INTO changes VALUES ('1', 'weight', to_jsonb(34),'01-03-2021 00:00:00'::TIMESTAMP);
entity_id | column_id | value | updated_at
-----------+-----------+-------+---------------------
1 | height | 140 | 2021-01-01 00:00:00
1 | weight | 30 | 2021-01-01 00:00:00
1 | height | 145 | 2021-01-02 00:00:00
1 | weight | 34 | 2021-01-03 00:00:00
我想要获得这张表的累积视图
entity_id | height | weight | updated_at
-----------+--------+--------+---------------------
1 | 140 | 30 | 2021-01-01 00:00:00
1 | 145 | 30 | 2021-01-02 00:00:00
1 | 145 | 34 | 2021-01-03 00:00:00
我当前的查询看起来很有效
SELECT
entity_id,
coalesce(change->'height', lag(change->'height', 1, null) over (partition by entity_id order by updated_at)) as height,
coalesce(change->'weight', lag(change->'weight', 1, null) over (partition by entity_id order by updated_at)) as weight,
updated_at
FROM (
SELECT entity_id, json_object_agg(column_id, value) as change, updated_at FROM changes
GROUP BY entity_id, updated_at
) as changes;
但我不喜欢这里的json_object_agg
,我相信有一种方法可以在没有冗余聚合的情况下完成它?我错过了一些使用窗口聚合函数的方法.
UPD.@SelVazi帮助让Query变得更好,但我觉得这不是最终的解决方案.
with cte as (
SELECT
entity_id,
max(case when column_id = 'height' then value::int end) as height,
max(case when column_id = 'weight' then value::int end) as weight,
updated_at
from changes
GROUP by entity_id, updated_at
)
select
entity_id,
coalesce(height, lag(height) over (partition by entity_id order by updated_at)) as height,
coalesce(weight, lag(weight) over (partition by entity_id order by updated_at)) as weight,
updated_at
from cte;