【问题标题】:Access (and count) just object values from Postgres JSONB array of objects仅访问(并计算)来自 Postgres JSONB 对象数组的对象值
【发布时间】:2018-10-27 22:15:41
【问题描述】:

我在 Postgres 数据库中有一个 JSONB 列。我正在存储一个 JSON 对象数组,每个对象都有一个键值对。我敢肯定我本可以设计得更好,但现在我被困住了。

id | reviews
------------------
 1 | [{"apple": "delicious"}, {"kiwi": "not-delicious"}]
 2 | [{"orange": "not-delicious"}, {"pair": "not-delicious"}]
 3 | [{"grapes": "delicious"}, {"strawberry": "not-delicious"}, {"carrot": "delicious"}]

假设这个表被称为tasks。虽然每个对象中的键是不可预测的,但值是可预测的。对于每一行,我想知道 reviews 数组中“美味”的数量和“不美味”的数量。

编辑澄清:

我正在寻找上表中每个id/row 的美味/不美味计数。示例所需的输出:

id | delicious | not_delicious
-------------------------------
 1 |         1 |             1
 2 |         0 |             2
 3 |         2 |             1

【问题讨论】:

    标签: sql postgresql jsonb


    【解决方案1】:

    让我们说 r 是你的桌子:

    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)
    

    然后:

    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)
    

    我使用 ctid 作为行标识符,因为我没有其他列并且不想长 reviews

    显然每行都聚集了美味:

    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)
    

    更新帖子

    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)
    

    【讨论】:

    • 我会澄清我的问题,因为这不是我想要的。抱歉,但感谢您的回复。
    • @user94154 我得到了其他结果数字,但它们看起来对我来说是正确的
    • 感谢更新并发现我的错误。我更新了我的帖子来解决这个问题。
    • 如果答案可以接受,请接受和/或投票
    猜你喜欢
    • 1970-01-01
    • 2019-07-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-29
    • 2016-09-04
    • 2023-04-08
    • 1970-01-01
    相关资源
    最近更新 更多