【问题标题】:select elements from jsonb postgres array从 jsonb postgres 数组中选择元素
【发布时间】:2021-01-08 16:51:45
【问题描述】:

我的数据库中有这个 jsonb。 当且仅当前一个元素处于状态 3 时,我才需要显示处于状态 1 的元素

我需要进行为我带来满足条件的元素的查询。

可以使用 postgres 吗?

 [
    {
        "state": 3,
        "activity": "EJECUCIÓN",
        "final_date": "2020-02-24",
        "activity_id": 1,
        "current_days": -7,
        "initial_date": "2020-02-24",

    },
    {
        "state": 1,
        "activity": "REVISIÓN",
        "final_date": "2020-02-25",
        "activity_id": 2,
        "current_days": 0,
        "initial_date": "2020-02-25",

    },
    {
        "state": 0,    
        "activity": "RECEPCIÓN",
        "final_date": "2020-02-27",
        "activity_id": 4,
        "current_days": 0,
        "initial_date": "2020-02-27"


    } ]

【问题讨论】:

    标签: arrays json postgresql window-functions unnest


    【解决方案1】:

    您可以将 json 数组取消嵌套到子查询中的行,然后使用窗口函数检索“前一个”数组元素。然后剩下要做的就是过滤。

    假设您的 json(b!) 数据存储在表 js 的列 mytable 中,您可以将其表述为:

    select x.obj
    from mytable t
    cross join lateral (
        select x.obj, lag(obj) over(order by rn) lag_obj
        from jsonb_array_elements(t.js) with ordinality as x(obj, rn)
    ) x
    where (obj ->> 'state')::int = 1 and (lag_obj ->> 'state')::int = 3
    

    Demo on DB Fiddle

    【讨论】:

    • 请注意,如果 json-array 本身没有排序,但顺序应该从"initial_date""final_date" 派生,可以通过将(ORDER BY rn) 更改为例如(ORDER BY x.obj->>'initial_date') 轻松完成。
    • 如果 state1 的对象是第一个它没有先前的对象,它也应该显示它 [ { "state": 1, "activity": "EJECUCIÓN", }, { "state": 0,“活动”:“REVISIÓN”,},{“状态”:0,“活动”:“RECEPCIÓN”,}]
    • @DarioPaez:好的,只需将where 子句更改为:where (obj ->> 'state')::int = 1 and ((lag_obj ->> 'state')::int = 3 or lag_obj is null)
    【解决方案2】:

    您需要分解 json 来执行此操作:

    with invars as (
      select 1 as id, ' [
        {
            "state": 3,
            "activity": "EJECUCIÓN",
            "final_date": "2020-02-24",
            "activity_id": 1,
            "current_days": -7,
            "initial_date": "2020-02-24"
    
        },
        {
            "state": 1,
            "activity": "REVISIÓN",
            "final_date": "2020-02-25",
            "activity_id": 2,
            "current_days": 0,
            "initial_date": "2020-02-25"
    
        },
        {
            "state": 0,    
            "activity": "RECEPCIÓN",
            "final_date": "2020-02-27",
            "activity_id": 4,
            "current_days": 0,
            "initial_date": "2020-02-27"
    
    
        } ]'::jsonb as jcol
    ), expand as (
      select i.id, 
             j.obj->>'state' as this_state,
             lag(j.obj->>'state') 
               over (partition by id
                         order by rn) as last_state,
             j.obj
        from invars i
             cross join lateral 
               jsonb_array_elements(jcol) 
                 with ordinality as j(obj, rn)
    )
    select *
      from expand
     where this_state = '1' 
       and last_state = '3'
    ;
    ┌────┬────────────┬────────────┬─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┐
    │ id │ this_state │ last_state │                                                                 obj                                                                 │
    ├────┼────────────┼────────────┼─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┤
    │  1 │ 1          │ 3          │ {"state": 1, "activity": "REVISIÓN", "final_date": "2020-02-25", "activity_id": 2, "current_days": 0, "initial_date": "2020-02-25"} │
    └────┴────────────┴────────────┴─────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────┘
    (1 row)
    
    

    【讨论】:

      猜你喜欢
      • 2017-07-24
      • 2015-07-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多