Sql 从jsonb列获取特定值

Sql 从jsonb列获取特定值,sql,json,postgresql,jsonb,Sql,Json,Postgresql,Jsonb,我有一张桌子Customer 客户ID(int) 客户名称(字符串) 客户订单(jsonB) 客户订单具有以下结构: { "nodeValue":[ { "key": "key1", "value": "value1" }, { "key": "key2", "value": "value2" }, { "key": "key3", "value": "value3" },

我有一张桌子
Customer

  • 客户ID(int)
  • 客户名称(字符串)
  • 客户订单(jsonB)
客户订单
具有以下结构:

{ 
 "nodeValue":[
   { 
      "key": "key1",
      "value": "value1"
   },
   { 
      "key": "key2",
      "value": "value2"
   },
   { 
      "key": "key3",
      "value": "value3"
   },
   { 
      "key": "key4",
      "value": "value4"
   },
   { 
      "key": "key5",
      "value": "value5"
   }
 ]
}
我正在尝试获取行
key='key3'和key='key4'
nodeValue
的值

例如:返回'key3'和'key4'的值,
其中key='key3'和key='key4'

我正在尝试做一些类似的事情:

SELECT value, value 
from public.customers 
where nodeValue.key3 = 'key3' 
  AND nodeValue.key4 = 'key4'
'{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
    "key4": "value4",
    "key5": "value5"
}'
结果:

价值1

价值2

请注意使用运算符->>以文本形式获取值


我怀疑你真正想要的是

SELECT
  (SELECT orders->>'value'
    FROM json_array_elements(customerOrders->'nodeValue') AS orders
    WHERE orders->>'key' = 'key3'
  ) AS value_key3,
  (SELECT orders->>'value'
    FROM json_array_elements(customerOrders->'nodeValue') AS orders
    WHERE orders->>'key' = 'key4'
  ) AS value_key4
FROM public.customers;
但实际上,您的数据结构不适合此目的。使用具有键和值作为属性的对象,而不是具有键-值对的数组。有了它,您可以使用

SELECT
  customerOrders->'nodeValue'->>'key3' AS value_key3,
  customerOrders->'nodeValue'->>'key4' AS value_key4
FROM public.customers;

首先,您需要创建一个类型(或表)

然后你可以使用这个函数

SELECT
    r_key1.value AS key1,
    r_key2.value AS key2
FROM
    customers c
    JOIN LATERAL jsonb_populate_recordset(NULL::key_value_type, customerOrders -> 'nodeValue') r_key1 
      ON r_key1.key = 'key1'
    JOIN LATERAL jsonb_populate_recordset(NULL::key_value_type, customerOrders -> 'nodeValue') r_key2 
      ON r_key2.key = 'key2'
或者使用
jsonb\u to\u记录集
功能(不创建类型)

这是两个备选方案的结果

| key1   | key2   |
| ------ | ------ |
| value1 | value2 |
获取
key='key3'和key='key4'
所在行的
nodeValue

最佳使用:

要使它快速对于大型表,请使用索引支持它。理想情况下,一个
jsonb\u路径\u ops
索引:

CREATE INDEX customer_nodeValue_idx ON customer
USING gin ((customerOrders->'nodeValue') jsonb_path_ops);  -- parentheses required
见:

你问题的后一个版本有点棘手:

返回'key3'和'key4'的值

第一个筛选符合上述条件的行(使用快速索引查找)。然后取消JSON文档的测试,并在
LATERAL
子查询中构建您的答案。应该是最简单、最干净、最快的。有关技术,请参见:

我在两个查询的结果中添加了
customerid
,以标识行。那是可选的

DBFIDLE(演示两者)

设计 您可以将臃肿的JSON布局简化为:

SELECT value, value 
from public.customers 
where nodeValue.key3 = 'key3' 
  AND nodeValue.key4 = 'key4'
'{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
    "key4": "value4",
    "key5": "value5"
}'
或者至少:

'[
    {
        "key1": "value1"
    },
    {
        "key2": "value2"
    },
    {
        "key3": "value3"
    },
    {
        "key4": "value4"
    },
    {
        "key5": "value5"
    }
]'

将使一切变得更简单、更小和更快。

键=键3和键=键4不可能发生。你是说还是?不,这两个条件都应该是真的。一个
key
变量不能同时具有
'key3'
'Key4'
两个值。你真的是指
key3='value3'和Key4='value4'
吗?Bergi完全正确,谢谢你的回答。但我正在寻找类似的东西:{key=“abs”,value=“1”},{key=“sup”,value=“1”},{key=“may”,value=“2”}。我想查询如下内容:选择值、来自客户的值,其中key=“abs”和key=“sup”
结果应该有2个值:1,1感谢答案,我的输出可以返回记录数组。
SELECT c.customerid, o.values
FROM   customer c
CROSS  JOIN LATERAL (
   SELECT ARRAY(
      SELECT o.ord->>'value'
      FROM   jsonb_array_elements(c.customerOrders->'nodeValue') o(ord)
      WHERE (o.ord->>'key' = 'key3' OR
             o.ord->>'key' = 'key4')
      )
   ) o(values)
WHERE  c.customerOrders->'nodeValue' @> '[{"key": "key3"}]'
AND    c.customerOrders->'nodeValue' @> '[{"key": "key4"}]';
'{
    "key1": "value1",
    "key2": "value2",
    "key3": "value3",
    "key4": "value4",
    "key5": "value5"
}'
'[
    {
        "key1": "value1"
    },
    {
        "key2": "value2"
    },
    {
        "key3": "value3"
    },
    {
        "key4": "value4"
    },
    {
        "key5": "value5"
    }
]'