我在PostgreSQL数据库中有一个表

CREATE TABLE js.orders (
    id serial NOT NULL PRIMARY KEY,
    info json NOT NULL
)

包含6行JSON数据:

select * from js.orders;

退货

 id |                                                info                                                
----+----------------------------------------------------------------------------------------------------
  1 | { "customer": "Kapil", "items": {"product": "Heineken","qty": 6}}
  2 | { "customer": "Satyen", "items": {"product": "Heineken","qty": 18}}
  3 | { "customer": "Rekha", "items": {"product": "Carlsberg","qty": 24}}
  4 | { "customer": "Madhuri", "items": {"product": "Kalyani","qty": 12}}
  5 | { "customer": "Srinivas", "items": {"product": "Kingfisher Strong","qty": 12}}
  6 | { "customer": "Saina", "items": [{"product": "Bira91","qty": 6},{"product": "Kalyani","qty": 6} ]}
(6 rows)

以下带有"WHERE"条件的"SELECT"查询:

SELECT info ->> 'customer' AS customer FROM js.orders WHERE info -> 'items' ->> 'product' = 'Heineken';

退货 the correct two rows:

customer 
----------
 Kapil
 Satyen
(2 rows)

但是,以下查询应返回两行:

SELECT info ->> 'customer' AS customer FROM js.orders WHERE info -> 'items' ->> 'product' = 'Kalyani';

but 退货 only one row:

    customer     
-----------------
 Madhuri
(1 row)

显然,"Customer":"Sania"的行有一个"Items"列表,而不是一个单独的"Items",这是导致这个问题的原因.我应该如何修改我的查询以返回正确的行数.或者是数据必须重新格式化,否则.

站台是

'PostgreSQL 14.10 (Ubuntu 14.10-0ubuntu0.22.04.1) on x86_64-pc-linux-gnu, compiled by gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0, 64-bit'

推荐答案

你的第一个问题是,你将 struct 化数据存储为JSON文档,而不是关系设计中的普通列,这将使存储和查询效率提高much倍.

您的第二个问题是在不需要的情况下更改所述JSON文档的 struct .有些关键字"Items"的值是object,有些是array.(它们都没有"列表",这在JSON terminology中是不存在的.)使查询更加复杂.

在坚持您不幸的设计的同时,使用jsonpath operator @?的查询仍然有效,因为它以默认的"松散"模式处理给定路径上的对象and数组:

SELECT info ->> 'customer' AS customer
FROM   orders
WHERE  info -> 'items' @? '$.product ? (@ == "Kalyani")';

要像原始查询一样只查看objects:

SELECT id, info ->> 'customer' AS customer
FROM   orders
WHERE  info -> 'items' @? 'strict $.product ? (@ == "Kalyani")';

fiddle

Requires Postgres 12 or later, where the SQL/JSON path language was added. And assumes jsonb as data type, not json. The former is typically preferable anyway.
You might want index support for that. See:

Sql相关问答推荐

在postgresql中使用来自另一个字段的日期名称作为JSONB查询中的关键字

使用交叉应用透视表在SQL中转换分段时间段&

SQL—如何在搜索的元素之后和之前获取元素?

如何在presto/SQL中使用两个数组列创建(分解)单独的行

如果元素包含通过SQL指定的字符串,则过滤掉数组元素

值对于类型字符来说太长

使用SQL创建列出两个时间戳之间小时数的列

我可以在SQL的IN子句中使用比子查询包含的值更少的值吗?

是否可以为表中的所有列生成散列值?

Redshift PL/pgSQL循环中的参数化列名

在xml.Modify方法中使用子字符串和可能的替代方法

使用拆分器将已分组的不同值连接在一起

从单个表达式中的分隔字符串中取平均值

按行值出现的顺序对行值进行分组

用替代方案替换 SQL Cursor 以提高性能

SQL 中的第一个值和倒数第二个值

SQL Server中使用min()和max()从选定的特定值id表中删除不必要的时间

JSON对象查询SQL服务器

为 sqlite 全文搜索 (fts) 创建触发器时出现虚拟表的不安全使用

并非所有变量都绑定在 PL SQL 函数中