0

我之前发过类似的帖子,但由于上下文错误而将其删除。

我的数据库中的一个表包含一个 JSONB 列,其中包含一组 JSON 对象。session它与我在下面模拟的表格示例没有什么不同。

ID 用户身份 快照 插入的_at
1 37 {购物车:[{product_id:1,price_in_cents:3000,名称:“产品A”},{product_id:2,price_in_cents:2500,名称:“产品B”}]} 2022-01-01 20:00:00.000000
2 24 {购物车:[{product_id:1,price_in_cents:3000,名称:“产品A”},{product_id:3,price_in_cents:5500,名称:“产品C”}]} 2022-01-02 20:00:00.000000
3 88 {购物车:[{product_id:4,price_in_cents:1500,名称:“产品D”},{product_id:2,price_in_cents:2500,名称:“产品B”}]} 2022-01-03 20:00:00.000000

我用来从该表中检索记录的查询如下。

SELECT sessions.*
FROM sessions
INNER JOIN LATERAL (
    SELECT *
    FROM jsonb_to_recordset(sessions.snapshot->'cart')
    AS product(
        "product_id" integer,
        "name" varchar,
        "price_in_cents" integer
    )
) AS cart ON true;

我一直在尝试更新上面的查询以仅检索会话表中购物车中所有产品的price_in_cents值都大于的记录2000

到目前为止,我在形成这个查询方面没有任何成功,但如果有人能指出我正确的方向,我将不胜感激。

4

3 回答 3

1

您可以使用 JSON 路径表达式:

select *
from sessions
  ...
where not sessions.snapshot @@ '$.cart[*].price_in_cents <= 2000'

没有 JSON 路径表达式可以检查所有数组元素是否大于 2000。因此,这将返回没有元素小于 2000 的那些行——因为这可以用 JSON 路径表达式来表示。

于 2022-03-01T15:39:03.587 回答
1

这是基于原始查询的想法的一种可能的解决方案。购物车 JSON 数组对象的每个元素都连接到sessions其父行。现在需要添加 WHERE 子句条件,因为所需的 JSON 数组元素已公开。

SELECT *
FROM (
  SELECT
    sess.id,
    sess.user_id,
    sess.inserted_at,
    cart_items.cart_name,
    cart_items.cart_product_id,
    cart_items.cart_price_in_cents
  FROM sessions sess,
    LATERAL (SELECT (snapshot -> 'cart') snapshot_cart FROM sessions WHERE id = sess.id) snap_arr,
    LATERAL (SELECT
               (value::jsonb ->> 'name')::text cart_name,
               (value::jsonb -> 'product_id')::int cart_product_id,
               (value::jsonb -> 'price_in_cents')::int cart_price_in_cents
             FROM JSONB_ARRAY_ELEMENTS(snap_arr.snapshot_cart)) cart_items
) session_snapshot_cart_product;

解释 :

  • sessionscart中提取数组并按sessions行连接
  • 然后使用该函数cart的第二个连接将 JSON 数组的必要项取消嵌套JSONB_ARRAY_ELEMENTS(jsonb)
于 2022-03-01T20:10:15.880 回答
0

以下对我来说效果很好,让我可以灵活地使用不同的比较运算符,而不仅仅是诸如==or之类的比较运算符<=

在我需要构建的一个场景中,我还需要让我WHERE在子查询中也使用IN比较运算符与一组值进行比较,这在使用其他一些解决方案时是不可行的。

将其留在这里以防其他人遇到与我相同的问题,或者其他人找到更好的解决方案或想提出建议以建立此问题。

SELECT *
FROM sessions
WHERE NOT EXISTS (
    SELECT sessions.*
    FROM sessions
    INNER JOIN LATERAL (
        SELECT *
        FROM jsonb_to_recordset(sessions.snapshot->'cart')
        AS product(
            "product_id" integer,
            "name" varchar,
            "price_in_cents" integer
        )
    ) AS cart ON true
    WHERE name ILIKE "Product%";
)
于 2022-03-02T01:00:21.637 回答