Postgres 如何将 json 数组解包到列中,然后重新打包,但保留数据类型?
How can Postgres unpack a json array into a column then re-pack it, but preserve the data type?
这是一些数据:
create table t
(id numeric, ja json, cr timestamp with time zone);
insert into t
values
(1,'[1,2,3]','2019-01-01 00:00:00+0'),
(1,'[3,4,5]','2019-02-01 00:00:00+0'),
(2,'["a","b"]','2019-01-01 00:00:00+0');
这是一个解包 json 数组的查询,只保留给定时间的最新数组元素(一月“3”被删除,二月“3”被删除),然后重新打包数据:
SELECT r.id, json_agg(r.v), r.cr
FROM
(
SELECT
r.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v ORDER BY t.cr DESC) as rn
FROM
t
CROSS JOIN LATERAL json_array_elements_text(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr
部分过程涉及将 json 值转换为文本,以便 postgres 可以将它们分组到 window 函数中,这意味着当重新打包为数组时,数字已变为文本:
id v cr
1 ["1","2"] 2019-01-01 00:00:00+0
1 ["3","4","5"] 2019-02-01 00:00:00+0
2 ["a","b"] 2019-01-01 00:00:00+0
在将它们打包回 json 数组的过程中,是否有办法将数字字符串转换回数字?
不要将它们转换为文本,您只需要 partition by
:
SELECT r.id, json_agg(r.v), r.cr
FROM (
SELECT t.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v::text ORDER BY t.cr DESC) as rn
FROM t
CROSS JOIN LATERAL json_array_elements(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr
您在使用 json_array_elements_text()
时将元素转换为文本。只需使用 json_array_elements()
即可保留数据类型。对于 window 函数,您可以将其单独转换为 text
。
SELECT r.id, json_agg(r.v), r.cr
FROM
(
SELECT
t.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v::text ORDER BY t.cr DESC) as rn
FROM
t
CROSS JOIN LATERAL json_array_elements(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr
这是一些数据:
create table t
(id numeric, ja json, cr timestamp with time zone);
insert into t
values
(1,'[1,2,3]','2019-01-01 00:00:00+0'),
(1,'[3,4,5]','2019-02-01 00:00:00+0'),
(2,'["a","b"]','2019-01-01 00:00:00+0');
这是一个解包 json 数组的查询,只保留给定时间的最新数组元素(一月“3”被删除,二月“3”被删除),然后重新打包数据:
SELECT r.id, json_agg(r.v), r.cr
FROM
(
SELECT
r.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v ORDER BY t.cr DESC) as rn
FROM
t
CROSS JOIN LATERAL json_array_elements_text(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr
部分过程涉及将 json 值转换为文本,以便 postgres 可以将它们分组到 window 函数中,这意味着当重新打包为数组时,数字已变为文本:
id v cr
1 ["1","2"] 2019-01-01 00:00:00+0
1 ["3","4","5"] 2019-02-01 00:00:00+0
2 ["a","b"] 2019-01-01 00:00:00+0
在将它们打包回 json 数组的过程中,是否有办法将数字字符串转换回数字?
不要将它们转换为文本,您只需要 partition by
:
SELECT r.id, json_agg(r.v), r.cr
FROM (
SELECT t.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v::text ORDER BY t.cr DESC) as rn
FROM t
CROSS JOIN LATERAL json_array_elements(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr
您在使用 json_array_elements_text()
时将元素转换为文本。只需使用 json_array_elements()
即可保留数据类型。对于 window 函数,您可以将其单独转换为 text
。
SELECT r.id, json_agg(r.v), r.cr
FROM
(
SELECT
t.id,
j.v,
t.cr,
ROW_NUMBER() OVER(PARTITION BY t.id, j.v::text ORDER BY t.cr DESC) as rn
FROM
t
CROSS JOIN LATERAL json_array_elements(t.ja) j(v)
) r
WHERE r.rn = 1
GROUP BY r.id, r.cr