如何在postgres中将json数组转换为行

k4p*_*ppa 45 arrays postgresql json

我在postgres数据库中存储了一个json数组.json看起来像这样:

    [
        {
            "operation": "U",
            "taxCode": "1000",
            "description": "iva description",
            "tax": "12"
        },
        {
            "operation": "U",
            "taxCode": "1001",
            "description": "iva description",
            "tax": "12"
        },
        {
            "operation": "U",
            "taxCode": "1002",
            "description": "iva description",
            "tax": "12"
        }
    ]
Run Code Online (Sandbox Code Playgroud)

现在我需要SELECT数组,以便任何元素都在查询结果的不同行中.所以我执行的SELECT语句必须以这种方式返回数据:

 data
--------------------------------------------------------------------------------------
 { "operation": "U", "taxCode": "1000", "description": "iva description", "tax":"12"}
 { "operation": "U", "taxCode": "1001", "description": "iva description", "tax":"12"}
 { "operation": "U", "taxCode": "1002", "description": "iva description", "tax":"12"}
Run Code Online (Sandbox Code Playgroud)

我尝试过使用这个unnest()功能

SELECT unnest(json_data::json)
FROM my_table
Run Code Online (Sandbox Code Playgroud)

但它不接受这种jsonb类型

k4p*_*ppa 46

我在评论部分发布了pozs最初写的答案.

unnest() 适用于PostgreSQL的数组类型.

而是可以使用以下功能之一:

  • json_array_elements(json) (9.3+)
  • jsonb_array_elements(jsonb) (9.4+)
  • json[b]_array_elements_text(json[b]) (9.4+)

示例:

select * from json_array_elements('[1,true, [2,false]]')
Run Code Online (Sandbox Code Playgroud)

产值

 -------------
 | 1         |
 -------------
 | true      |
 -------------
 | [2,false] |
 -------------
Run Code Online (Sandbox Code Playgroud)

这里可以找到v9.4的文档.

  • 还值得一提的是,带有“_text”的函数删除了 JSON 字符串中烦人的引号 (4认同)

小智 27

我建议在你的情况下使用json_to_recordset命令.那么你的SQL应该是:

select *
from json_to_recordset('[{"operation":"U","taxCode":1000},{"operation":"U","taxCode":10001}]')
as x("operation" text, "taxCode" int);
Run Code Online (Sandbox Code Playgroud)

输出是:

------------------------
|   |operation|taxCode |
------------------------
| 1 |   "U"   |   1000 |
------------------------
| 2 |   "U"   |  10001 |
------------------------
Run Code Online (Sandbox Code Playgroud)

可以自由地进一步扩展示例的列(或JSON键).


Env*_*vek 20

更难的例子:

假设您有一个包含每行包含jsonb数组的行的表,并且您希望展开(或不需要)所有数组并对其中包含的记录执行一些聚合计算.

表(让它categories):

 id | specifics (jsonb)
-----------------------------------------------------------------------------------
  1 | [{"name": "Brand", "required": true}, {"name": "Color", "required": false}]
  2 | [{"name": "Brand", "required": false}, {"name": "Color", "required": false}]
Run Code Online (Sandbox Code Playgroud)

因此,如果您想要计算,有多少必需的细节,您将需要使用这样的查询:

SELECT specs.name, COUNT(*) AS total
FROM 
  categories, 
  jsonb_to_recordset(categories.specifics) AS specs(name jsonb, required boolean)
WHERE 
  specs.required = TRUE
  -- AND any other restrictions you need
GROUP BY specs.name
ORDER BY total DESC;
Run Code Online (Sandbox Code Playgroud)

FROM x, function(x.column)是一个缩短形式的横向连接,它有效地将每一行categories与由jsonb_to_recordset同一行中的jsonb数组的函数创建的虚拟表连接起来.