aid*_*dan 2 sql postgresql json
我有一个表(表 A),其中包含一个包含 JSON 编码数据的文本列。
JSON 数据始终是一个包含一到几千个普通对象的数组。
我有另一个包含几列的表(表 B),包括一个数据类型为“JSON”的列
我想从表 A 中选择所有行,将 json 数组拆分为其元素并将每个元素插入表 B
奖励目标:每个对象(几乎)总是有一个键,x。我想将xout的值拉入列,并x从原始对象(如果存在)中删除。
例如:表 A
| id | json_array (text) |
+----+--------------------------------+
| 1 | '[{"x": 1}, {"y": 8}]' |
| 2 | '[{"x": 2, "y": 3}, {"x": 1}]' |
| 3 | '[{"x": 8, "z": 2}, {"z": 3}]' |
| 4 | '[{"x": 5, "y": 2, "z": 3}]' |
Run Code Online (Sandbox Code Playgroud)
...将成为:表B
| id | a_id | x | json (json) |
+----+------+------+--------------------+
| 0 | 1 | 1 | '{}' |
| 1 | 1 | NULL | '{"y": 8}' |
| 2 | 2 | 2 | '{"y": 3}' |
| 3 | 2 | 1 | '{}' |
| 4 | 3 | 8 | '{"y": 2}' |
| 5 | 3 | NULL | '{"z": 3}' |
| 6 | 4 | 5 | '{"y": 2, "z": 3}' |
Run Code Online (Sandbox Code Playgroud)
这最初必须处理几百万行,然后需要定期运行,因此使其高效将是一个优先事项。
是否可以在不使用循环和 PL/PgSQL 的情况下执行此操作?我没有取得太大进展。
该json数据类型不是特别适合(或打算)在数据库级别进行修改。"x"因此从 JSON 对象中提取对象是很麻烦的,尽管它可以完成。
您应该创建您的表 B(希望"json"使用比 更具创意的列名;我在item这里使用)并使id列 aserial从 0 开始。一个纯json解决方案看起来像这样:
INSERT INTO b (a_id, x, item)
SELECT sub.a_id, sub.x,
('{' ||
string_agg(
CASE WHEN i.k IS NULL THEN '' ELSE '"' || i.k || '":' || i.v END,
', ') ||
'}')::json
FROM (
SELECT a.id AS a_id, (j.items->>'x')::integer AS x, j.items
FROM a, json_array_elements(json_array) j(items) ) sub
LEFT JOIN json_each(sub.items) i(k,v) ON i.k <> 'x'
GROUP BY sub.a_id, sub.x
ORDER BY sub.a_id;
Run Code Online (Sandbox Code Playgroud)
在子查询中,这会提取a_id和x值以及 JSON 对象。在外部查询中,JSON 对象被分解为单独的部分,并且带有键的对象x被抛出 (the LEFT JOIN ON i.k <> 'x')。在选择列表中,这些片段通过字符串连接重新组合在一起并组合成复合对象。
这必然是这样的,因为json没有任何结果的内置操作函数。这适用于 PG 版本 9.3+,即自远古以来就 JSON 支持而言。
如果您使用的是 PG9.5+,则通过强制转换为解决方案要简单得多jsonb:
INSERT INTO b (a_id, x, item)
SELECT a.id, (j.items->>'x')::integer, j.items #- '{x}'
FROM a, jsonb_array_elements(json_array::jsonb) j(items);
Run Code Online (Sandbox Code Playgroud)
数据类型的#-操作符在jsonb这里完成了所有脏活。显然,在幕后有很多工作正在进行,转换json为jsonb,因此如果您发现需要更频繁地操作 JSON 对象,那么最好先使用该jsonb类型。在您的情况下,我建议您对EXPLAIN ANALYZE SELECT ...大约INSERT10,000 行进行一些基准测试(您可以放心地忘记while 测试),以查看哪些最适合您的设置。
| 归档时间: |
|
| 查看次数: |
5796 次 |
| 最近记录: |