在 PostgreSQL 中搜索嵌套的 jsonb 数组
Searching nested jsonb array in PostgreSQL
我有一个订单 table,我将订单摘要存储在 jsonb
列中
{"users": [
{"food": [{"name": "dinner", "price": "100"}], "room": "2", "user": "bob"},
{"room": "3", "user": "foo"}
]}
现在我想查询所有 users
及其 food->name
。
我尝试了以下方法,但这也给了我用户 foo,没有食物。
select
jsonb_array_elements(jsonb_array_elements(summary->'users')->'food')->>'name' as food,
jsonb_array_elements(summary->'users')->>'user' as user_name
from orders;
food | user_name
-------+-----------
dinner | bob
dinner | foo
我将如何进行这样的查询?
更新
我也有这样的夏天有两种食物选择
{"users": [
{"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "100"}], "room": "2", "user": "bob"},
{"room": "3", "user": "foo"}
]}
然后我得到:
food | user_name
-----------+-----------
dinner | bob
breakfast | foo
理想情况下我想要
food | user_name
----------------------+-----------
dinner, breakfast | bob
好吧,如果你这样做了
SELECT jsonb_array_elements(summary->'users') as users FROM orders;
你得到
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ users │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ {"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "50"}], "room": "2", "user": "bob"} │
│ {"room": "3", "user": "foo"} │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
让我们把这个 select 放在另一个里面,select我们需要的东西:
SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s;
┌───────────┬──────────┐
│ user_name │ food │
├───────────┼──────────┤
│ "bob" │ "dinner" │
│ "foo" │ (null) │
└───────────┴──────────┘
我们很接近了。我们只需要添加一个WHERE
.
SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
导致
┌───────────┬──────────┐
│ user_name │ food │
├───────────┼──────────┤
│ "bob" │ "dinner" │
└───────────┴──────────┘
如果您的食物数组中有更多数据,例如
'{"users": [{"food": [{"name": "dinner", "price": "100"}, {"name" : "breakfast", "price" : "50"}], "room": "2", "user": "bob"}, {"room": "3", "user": "foo"}]}'
你可以做到
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
和
┌───────────┬───────────┐
│ user_name │ food │
├───────────┼───────────┤
│ "bob" │ dinner │
│ "bob" │ breakfast │
└───────────┴───────────┘
重写上述查询以使用通用 Table 表达式
WITH users_data AS (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food
FROM users_data
WHERE (users->'food') is not null
) SELECT * FROM user_food;
现在我们只需要按user_name
分组
WITH users_data AS (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food
FROM users_data
WHERE (users->'food') is not null
) SELECT user_name, array_agg(food) foods FROM user_food GROUP BY user_name;
最终结果
┌───────────┬────────────────────┐
│ user_name │ foods │
├───────────┼────────────────────┤
│ "bob" │ {dinner,breakfast} │
└───────────┴────────────────────┘
这是我能想到的最好的了。如果您找到更好的方法,请告诉我。
我有一个订单 table,我将订单摘要存储在 jsonb
列中
{"users": [
{"food": [{"name": "dinner", "price": "100"}], "room": "2", "user": "bob"},
{"room": "3", "user": "foo"}
]}
现在我想查询所有 users
及其 food->name
。
我尝试了以下方法,但这也给了我用户 foo,没有食物。
select
jsonb_array_elements(jsonb_array_elements(summary->'users')->'food')->>'name' as food,
jsonb_array_elements(summary->'users')->>'user' as user_name
from orders;
food | user_name
-------+-----------
dinner | bob
dinner | foo
我将如何进行这样的查询?
更新
我也有这样的夏天有两种食物选择
{"users": [
{"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "100"}], "room": "2", "user": "bob"},
{"room": "3", "user": "foo"}
]}
然后我得到:
food | user_name
-----------+-----------
dinner | bob
breakfast | foo
理想情况下我想要
food | user_name
----------------------+-----------
dinner, breakfast | bob
好吧,如果你这样做了
SELECT jsonb_array_elements(summary->'users') as users FROM orders;
你得到
┌──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
│ users │
├──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
│ {"food": [{"name": "dinner", "price": "100"}, {"name": "breakfast", "price": "50"}], "room": "2", "user": "bob"} │
│ {"room": "3", "user": "foo"} │
└──────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
让我们把这个 select 放在另一个里面,select我们需要的东西:
SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s;
┌───────────┬──────────┐
│ user_name │ food │
├───────────┼──────────┤
│ "bob" │ "dinner" │
│ "foo" │ (null) │
└───────────┴──────────┘
我们很接近了。我们只需要添加一个WHERE
.
SELECT users->'user' as user_name, users->'food'->0->'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
导致
┌───────────┬──────────┐
│ user_name │ food │
├───────────┼──────────┤
│ "bob" │ "dinner" │
└───────────┴──────────┘
如果您的食物数组中有更多数据,例如
'{"users": [{"food": [{"name": "dinner", "price": "100"}, {"name" : "breakfast", "price" : "50"}], "room": "2", "user": "bob"}, {"room": "3", "user": "foo"}]}'
你可以做到
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food FROM (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
) as s WHERE (users->'food') is not null;
和
┌───────────┬───────────┐
│ user_name │ food │
├───────────┼───────────┤
│ "bob" │ dinner │
│ "bob" │ breakfast │
└───────────┴───────────┘
重写上述查询以使用通用 Table 表达式
WITH users_data AS (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food
FROM users_data
WHERE (users->'food') is not null
) SELECT * FROM user_food;
现在我们只需要按user_name
WITH users_data AS (
SELECT jsonb_array_elements(summary->'users') as users FROM orders
), user_food AS (
SELECT users->'user' as user_name, jsonb_array_elements(users->'food')->>'name' as food
FROM users_data
WHERE (users->'food') is not null
) SELECT user_name, array_agg(food) foods FROM user_food GROUP BY user_name;
最终结果
┌───────────┬────────────────────┐
│ user_name │ foods │
├───────────┼────────────────────┤
│ "bob" │ {dinner,breakfast} │
└───────────┴────────────────────┘
这是我能想到的最好的了。如果您找到更好的方法,请告诉我。