【问题标题】:joining and filtering on json textfield in postgres db在 postgres db 中加入和过滤 json 文本字段
【发布时间】:2022-01-09 17:28:10
【问题描述】:

我正在使用 postgres v.10 数据库

因此,在我的示例中,我需要归还所有空置但有电的建筑物。

我有一张桌子,里面有所有的建筑,我可以过滤掉空的建筑。

我的问题是有关 elektricity 的信息在成本表中,而我需要的信息存储在 json 格式的文本字段中。它可能看起来像这样:

{"splitkey_hash":{"100":[{"part":"0.0","notes":"blabla","uid":"100_0","id":"100","active_from":"2020-01-01"},{"part":"1.0","notes":"roar","uid":"100_1","id":"100","active_from":"2020-06-01"},{"part":"1.0","notes":null,"uid":"100_2","id":"100","active_from":"2021-01-01"}],"200":[{"part":"0.0","notes":null,"uid":"200_0","id":"200","active_from":"2015-01-01"}],"300":[{"part":"1.0","notes":null,"uid":"300_0","id":"300","active_from":"2013-01-01"}],"400":[{"part":"1.0","notes":"abc","uid":"400_0","id":"400","active_from":"2019-01-01"},{"part":"1.0","notes":null,"uid":"400_1","id":"400","active_from":"2020-09-01"}]}}

JSON 格式:

{
  "splitkey_hash": {
    "100": [
      {
        "part": "0.0",
        "notes": "blabla",
        "uid": "100_0",
        "id": "100",
        "active_from": "2020-01-01"
      },
      {
        "part": "1.0",
        "notes": "roar",
        "uid": "100_1",
        "id": "100",
        "active_from": "2020-06-01"
      },
      {
        "part": "1.0",
        "notes": null,
        "uid": "100_2",
        "id": "100",
        "active_from": "2021-01-01"
      }
    ],
    "200": [
      {
        "part": "0.0",
        "notes": null,
        "uid": "200_0",
        "id": "200",
        "active_from": "2015-01-01"
      }
    ],
    "300": [
      {
        "part": "1.0",
        "notes": null,
        "uid": "300_0",
        "id": "300",
        "active_from": "2013-01-01"
      }
    ],
    "400": [
      {
        "part": "1.0",
        "notes": "abc",
        "uid": "400_0",
        "id": "400",
        "active_from": "2019-01-01"
      },
      {
        "part": "1.0",
        "notes": null,
        "uid": "400_1",
        "id": "400",
        "active_from": "2020-09-01"
      }
    ]
  }
}

Building_id = id (json)
Elektricity active = "part": "1.0" (json)
Not active = "part": "0.0" (json)

因此,如果我想问一下 buildung 100 是否在 2020 年 2 月 1 日启用了 elektricity,答案应该是否定的。但是在 2020-06-01 之后会是。

希望你们不明白我在寻找什么?我想以某种方式将 json 中的信息与我所有的 ID 加入到空 buildungs 中,并使用日期进行过滤。

【问题讨论】:

    标签: json postgresql join


    【解决方案1】:

    假设建筑物 id 的类型为整数,那么以下查询将返回给定 ref_date 的 active = true 或 false 的所有空建筑物:

    来自 PostgreSQL v12:

    SELECT DISTINCT ON ( o->'id')
           o->'id'
         , first_value(o->>'part') OVER(PARTITION BY o->'id' ORDER BY (o->>'active_from') :: date DESC) = '1.0' AS active -- = true if active, false if not active
      FROM (your_empty_building_id_list) AS l
     INNER JOIN 
         ( your_cost_table AS t
           CROSS JOIN LATERAL jsonb_path_query((t.your_json_column :: jsonb)->'splitkey_hash'
    , '$.*[*]') AS o
         )
        ON l.id = (o->>'id') :: integer
    WHERE (o->>'active_from') :: date <= ref_date -- ref_date to be replaced by the effective date used for the query
    

    在 PostgreSQL v12 之前:

    SELECT DISTINCT ON ( o->'id')
           o->'id'
         , first_value(o->>'part') OVER(PARTITION BY o->'id' ORDER BY (o->>'active_from') :: date DESC) = '1.0' AS active -- = true if active, false if not active
      FROM (your_empty_building_id_list) AS l
     INNER JOIN 
         ( your_cost_table AS t
           CROSS JOIN LATERAL jsonb_each((t.your_json_column :: jsonb)->'splitkey_hash') AS m(key, value)
           CROSS JOIN LATERAL jsonb_array_elements(m.value) AS o
         ) ON l.id = o->>'id'
        WHERE (o->>'active_from') :: date <= ref_date -- ref_date to be replaced by the effective date used for the query
    

    dbfiddle查看测试结果

    【讨论】:

    • 遗憾的是它在 V.10 中不起作用dbfiddle.uk/…
    • 我已经更新了对早于 v12 的 postgres 的查询。
    猜你喜欢
    • 1970-01-01
    • 2021-06-10
    • 2017-12-06
    • 2014-12-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-19
    • 2010-11-30
    相关资源
    最近更新 更多