用于过滤 JSONB 数组中所有数组项满足条件的 SQL 查询
我以前发过类似的帖子,但由于上下文错误而删除了它。
我的数据库中的一个表包含一个 JSONB 列,其中包含一组 JSON 对象。它与我在下面模拟的这个 session
表示例没有什么不同。
id | user_id | snapshot | insert_at |
---|---|---|---|
1 | 37 | {购物车:[{product_id:1,price_in_cents:3000,name:“产品A”},{product_id:2,price_in_cents:2500,name:“产品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 | {cart :[{product_id:4,price_in_cents:1500, name: "product D"}, {product_id: 2, Price_in_cents: 2500, name: "product 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。
到目前为止,我在形成这个查询方面还没有取得任何成功,但如果这里有人能给我指出正确的方向,我将不胜感激。
I made a similar post before, but deleted it as it had contextual errors.
One of the tables in my database includes a JSONB column which includes an array of JSON objects. It's not dissimilar to this example of a session
table which I've mocked up below.
id | user_id | snapshot | inserted_at |
---|---|---|---|
1 | 37 | {cart: [{product_id: 1, price_in_cents: 3000, name: "product A"}, {product_id: 2, price_in_cents: 2500, name: "product B"}]} | 2022-01-01 20:00:00.000000 |
2 | 24 | {cart: [{product_id: 1, price_in_cents: 3000, name: "product A"}, {product_id: 3, price_in_cents: 5500, name: "product C"}]} | 2022-01-02 20:00:00.000000 |
3 | 88 | {cart: [{product_id: 4, price_in_cents: 1500, name: "product D"}, {product_id: 2, price_in_cents: 2500, name: "product B"}]} | 2022-01-03 20:00:00.000000 |
The query I've worked with to retrieve records from this table is as follows.
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;
I've been trying to update the query above to retrieve only the records in the sessions table for which ALL of the products in the cart have a price_in_cents
value of greater than 2000
.
To this point, I've not had any success on forming this query but I'd be grateful if anyone here can point me in the right direction.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
您可以使用 JSON 路径表达式:
没有 JSON 路径表达式可以检查所有数组元素是否大于 2000。因此,这将返回没有元素小于 2000 的那些行 - 因为可以使用 JSON 路径表达式来表达。
You can use a JSON path expression:
There is no JSON path expression that would check that all array elements are greater 2000. So this returns those rows where no element is smaller than 2000 - because that can be expressed with a JSON path expression.
这是基于您原始查询的想法的一种可能的解决方案。
购物车 JSON 数组对象的每个元素都连接到其
sessions
父行。既然所需的 JSON 数组元素已公开,您就需要添加 WHERE 子句条件。解释:
sessions
表中,提取cart
数组,并按sessions
行连接cart
的必要项目> 然后,使用JSONB_ARRAY_ELEMENTS(jsonb)
函数通过第二个连接解除 JSON 数组的嵌套Here is one possible solution based on the idea of your original query.
Each element of the cart JSON array object is joined to its
sessions
parent row. You 're left adding the WHERE clause conditions now that the wanted JSON array elements are exposed.Explanation :
sessions
table, thecart
array is exctracted and joined persessions
rowcart
JSON array is then unnested by the second join using theJSONB_ARRAY_ELEMENTS(jsonb)
function以下内容对我来说效果很好,并允许我灵活地使用不同的比较运算符,而不仅仅是
==
或<=
等运算符。在我需要构建的一个场景中,我还需要使用
IN
比较运算符将子查询中的WHERE
与值数组进行比较,这不是使用我们研究过的一些其他解决方案是可行的。将其留在这里,以防其他人遇到与我相同的问题,或者其他人找到更好的解决方案或想要在此基础上提出建议。
The following worked well for me and allowed me the flexibility to use different comparison operators other than just ones such as
==
or<=
.In one of the scenarios I needed to construct, I also needed to have my
WHERE
in the subquery also compare against an array of values using theIN
comparison operator, which was not viable using some of the other solutions that were looked at.Leaving this here in case others run into the same issue as I did, or if others find better solutions or want to propose suggestions to build upon this one.