加入和过滤 postgres 数据库中的 json 文本字段
joining and filtering on json textfield in postgres db
我正在使用 postgres v.10 数据库
所以在我的示例中,我需要 return 所有空置但通电的建筑物。
我有一个 table,里面有所有的建筑,我可以在其中过滤掉空的建筑。
我的问题是有关电力的信息需要支付费用 table,而我需要的信息存储在 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-02-01 激活了电力,答案应该是否定的。但是2020-06-01之后就是Yes了
希望你们明白我在找什么?我想以某种方式将 json 中的信息与我所有的空建筑 ID 结合起来,并使用日期进行过滤。
假设建筑物 id
是整数类型,则以下查询 returns 给定 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
中的测试结果
我正在使用 postgres v.10 数据库
所以在我的示例中,我需要 return 所有空置但通电的建筑物。
我有一个 table,里面有所有的建筑,我可以在其中过滤掉空的建筑。
我的问题是有关电力的信息需要支付费用 table,而我需要的信息存储在 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-02-01 激活了电力,答案应该是否定的。但是2020-06-01之后就是Yes了
希望你们明白我在找什么?我想以某种方式将 json 中的信息与我所有的空建筑 ID 结合起来,并使用日期进行过滤。
假设建筑物 id
是整数类型,则以下查询 returns 给定 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
中的测试结果