我目前正在使用postgres数据库,但我的知识仅限于SQL。我正在使用订单数据库,需要选择购买了所选产品的所有客户。我的表格如下:
order_id customer_name products_ordered
1 a {"apples":3, "pears":4}
2 b {"apples":4, "pears":4, "oranges":2}
3 c {"apples":2, "oranges":3}
4 a {"apples": 5}
5 c {"oranges": 4}
6 a {"oranges":1}
我需要检查哪些客户在某个时候点了每个产品,苹果,梨和橙子,所以输出应该如下:
customer_name
a
b
我没有访问数据库中的JSON对象的经验,我想知道如何检索一些客户列表,这些客户在某些时候订购了 [key of keys] 。
提前致谢!
答案 0 :(得分:1)
这不是最漂亮的查询,但它可以正常运作。
将json密钥解压缩到自己的记录中,按客户名聚合记录,然后进行包含数组的比较。有点滥用CTE来做这件事......
with
__customer_products as(
select
customer_name,
json_object_keys(products_ordered) as product_key
from
orders
),
__customer_products_merged as(
select
customer_name,
array_agg(product_key) as product_keys
from
__customer_products
group by
customer_name
)
select
customer_name
from
__customer_products_merged
where
product_keys @> array['apples', 'pears', 'oranges']
答案 1 :(得分:0)
如果您愿意创建一个自定义聚合函数,将多个JSONB值聚合为一个,并合并密钥,则可以使用简单查询执行此操作。
首先创建聚合函数:
create aggregate jsonb_object_agg(jsonb)
(
sfunc = 'jsonb_concat',
stype = jsonb,
initcond = '{}'
);
请注意,这与内置jsonb_object_agg()
不同,后者带有两个参数(键,值)。它使用jsonb_concat
函数||
将两个JSONB值合并为一个。
使用该聚合,您的查询就像:
一样简单select customer_name
from orders
group by customer_name
having jsonb_object_agg(products_ordered) ?& array['pears','apples', 'oranges'];
?&
运算符检查JSONB值中是否存在所有键。
如果没有聚合功能,您可以这样做:
select customer_name
from orders,
jsonb_each_text(products_ordered) as t(k,v)
group by customer_name
having jsonb_object_agg(t.k, t.v) ?& array['pears','apples', 'oranges'];
然而,这会将每个JSON值扩展为每个订单的多行,只是为了再次聚合 - 这会产生比“真实”聚合函数更大的中间结果,因此可能会更慢。
在线示例:http://rextester.com/EAZVG14239
以上所有内容均假设您的products_ordered
是JSONB
列。如果是JSON
列,则需要将其投放到JSONB