sql - Access (and count) just object values from Postgres JSONB array of objects
问题描述
I have a JSONB column in a Postgres database. I'm storing an array of JSON objects, each with a single key-value pair. I'm sure I could have designed this better, but for now I'm stuck with this.
id | reviews
------------------
1 | [{"apple": "delicious"}, {"kiwi": "not-delicious"}]
2 | [{"orange": "not-delicious"}, {"pair": "not-delicious"}]
3 | [{"grapes": "delicious"}, {"strawberry": "not-delicious"}, {"carrot": "delicious"}]
Suppose this table is called tasks
. While the keys in each of these objects are not predictable, the values are. For each row, I'd like to know the number of "delicious" and number of "not-delicious" values in the reviews
array.
Edit for clarification:
I'm looking for the delicious/not-delicious counts for each id
/row in the above table. Sample desired output:
id | delicious | not_delicious
-------------------------------
1 | 1 | 1
2 | 0 | 2
3 | 2 | 1
解决方案
lets say r is your table:
so=# select * from r;
reviews
-------------------------------------------------------------------------------------
[{"apple": "delicious"}, {"kiwi": "not-delicious"}]
[{"orange": "not-delicious"}, {"pair": "not-delicious"}]
[{"grapes": "delicious"}, {"strawberry": "not-delicious"}, {"carrot": "delicious"}]
(3 rows)
then:
so=# with j as (select jsonb_array_elements(reviews) a, r, ctid from r)
select jsonb_object_keys(a), a->>jsonb_object_keys(a),ctid from j;
jsonb_object_keys | ?column? | ctid
-------------------+---------------+-------
apple | delicious | (0,1)
kiwi | not-delicious | (0,1)
orange | not-delicious | (0,2)
pair | not-delicious | (0,2)
grapes | delicious | (0,3)
strawberry | not-delicious | (0,3)
carrot | delicious | (0,3)
(7 rows)
I used ctid as row identifier, cos I have no other column and did not want long reviews
and obviously aggregation of delicious per row:
so=# with j as (select jsonb_array_elements(reviews) a, r, ctid from r)
select ctid, a->>jsonb_object_keys(a), count(*) from j group by a->>jsonb_object_keys(a),ctid;
ctid | ?column? | count
-------+---------------+-------
(0,1) | delicious | 1
(0,3) | delicious | 2
(0,1) | not-delicious | 1
(0,2) | not-delicious | 2
(0,3) | not-delicious | 1
(5 rows)
for updated post
so=# with j as (select jsonb_array_elements(reviews) a, r, ctid from r)
, n as (
select ctid,a->>jsonb_object_keys(a) k from j
)
, ag as (
select ctid
, case when k = 'delicious' then 1 else 0 end deli
, case when k = 'not-delicious' then 1 else 0 end notdeli
from n
)
select ctid, sum(deli) deli, sum(notdeli) notdeli from ag group by ctid;
ctid | deli | notdeli
-------+------+---------
(0,1) | 1 | 1
(0,2) | 0 | 2
(0,3) | 2 | 1
(3 rows)
推荐阅读
- .net - 如何在 .NET Core 托管服务中的同一项目下安装多个服务
- c# - 开发需要依赖 dll 的动态 365 插件的最佳方法是什么?
- visual-studio-code - Code Runner 不适用于 VsCode 中的 Python
- spring - @PostConstruct:嵌套依赖项为空
- html - 当引导下拉菜单打开时如何切换按钮图标
- javascript - 无法对齐 svg 和
与 display:inline-block 在同一行?
- python - 将参数添加到应用于 pd.df 的 eval 函数
- javascript - Nodemon 安装不正确
- java - 如何计算(O)N中的最高和
- mysql - 迁移文件必须在 Sequelize 中吗?