Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/json/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
PostgreSQL:高效地将JSON数组拆分为行_Sql_Json_Postgresql - Fatal编程技术网

PostgreSQL:高效地将JSON数组拆分为行

PostgreSQL:高效地将JSON数组拆分为行,sql,json,postgresql,Sql,Json,Postgresql,我有一个表a,其中包含一个包含JSON编码数据的文本列 JSON数据始终是一个数组,包含一个到几千个普通对象 我有另一个表B,表B有几列,包括一个数据类型为“JSON”的列 我想选择表A中的所有行,将json数组拆分为其元素,并将每个元素插入表B 奖励目标:每个对象几乎都有一个键x。我想把x的值拉到列中,并从原始对象中删除x(如果存在) 例如:表A | id | json_array (text) | +----+----------------------------

我有一个表a,其中包含一个包含JSON编码数据的文本列

JSON数据始终是一个数组,包含一个到几千个普通对象

我有另一个表B,表B有几列,包括一个数据类型为“JSON”的列

我想选择表A中的所有行,将json数组拆分为其元素,并将每个元素插入表B

奖励目标:每个对象几乎都有一个键x。我想把x的值拉到列中,并从原始对象中删除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}]'   |
…将变成:表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}' |
这首先需要处理几百万行,然后需要定期运行,因此提高效率将是一个优先事项

不使用循环和PL/PgSQL是否可以做到这一点?我没有取得太大的进展。

json数据类型并不特别适合在数据库级别进行修改。因此,从JSON对象中提取x对象很麻烦,尽管这是可以做到的

您应该使用比json更具创造性的列名创建表B;我在这里使用item,并将id列设置为从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;

jsonb数据类型上的-operator在这里完成所有的脏工作。显然,将json转换为jsonb在幕后有很多工作要做,因此如果您发现需要更频繁地操作json对象,那么最好先使用jsonb类型。在你的情况下,我建议你做一些基准与解释分析选择。。。在测试大约10000行时,您可以放心地忘记插入,看看哪一行最适合您的设置。

您可以使用jsonb即PG9.5吗?json数据类型不适合操作对象,因为jsonb有更多的选项。使用jsonb删除x很容易,使用json则更复杂。不幸的是,我们还没有使用9.5,但希望不会太久。非常感谢你的全面回答。
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);