Oracle JSON_TABLE 到 PostgreSQL - 如何从 JSON 列中的第二个分层键开始搜索
Oracle JSON_TABLE to PostgreSQL - how to search from the second hierarchical key in a JSON column
我正在尝试将 Oracle 12c 查询迁移到 Postgres11.5。
这里是 json:
{
"cost": [{
"spent": [{
"ID": "HR",
"spentamount": {
"amount": 2000.0,
"country": "US"
}
}]
}],
"time": [{
"spent": [{
"ID": "HR",
"spentamount": {
"amount": 308.91,
"country": "US"
}
}]
}]
}
这是必须迁移到 Postgres 11.5 的查询:
select js.*
from P_P_J r,
json_table(r.P_D_J, '$.*[*]'
COLUMNS(NESTED PATH '$.spent[*]'
COLUMNS(
ID VARCHAR2(100 CHAR) PATH '$.ID',
amount NUMBER(10,4) PATH '$.spentamount.amount',
country VARCHAR2(100 CHAR) PATH '$.spentamount.country'))
) js
结果:
ID, amount, country
HR, 2000.0,US
HR,308.91,US
我这里有两个问题:
$.*[*]
是什么意思?
我们如何在 Postgres 中迁移这个查询,以便它直接查看 'spent' 而不是导航 'cost'->'spent' 或 'time' ->'spent'
在 Postgres 中没有 json_table 的直接替代品。您将不得不组合多个调用来分解 JSON 结构。
您没有向我们展示您的预期输出,但据我所知,以下内容应该也是如此:
select e.item ->> 'ID' as id,
(e.item #>> '{spentamount, amount}')::numeric as amount,
e.item #>> '{spentamount, country}' as country
from p_p_j r
cross join jsonb_each(r.p_d_j) as a(key, val)
cross join lateral (
select *
from jsonb_array_elements(a.val)
where jsonb_typeof(a.val) = 'array'
) as s(element)
cross join jsonb_array_elements(s.element -> 'spent') as e(item)
;
JSON 路径表达式 '$.*[*]
表示:遍历所有顶级键,然后遍历其中找到的所有数组元素和嵌套路径 '$.spent[*]'
然后再次遍历那里的所有数组元素。这些步骤反映在到达那里所需的三个 JSON 函数调用中。
使用 Postgres 12,这会更容易一些,因为这可以通过一次调用 jsonb_path_query()
来完成,它也使用 JSON 路径来访问使用非常相似的元素 JSON路径表达式:
select e.item ->> 'ID' as id,
(e.item #>> '{spentamount, amount}')::numeric as amount,
e.item #>> '{spentamount, country}' as country
from p_p_j r
cross join jsonb_path_query(r.p_d_j, '$.*[*].spent[*]') as e(item)
;
我正在尝试将 Oracle 12c 查询迁移到 Postgres11.5。
这里是 json:
{
"cost": [{
"spent": [{
"ID": "HR",
"spentamount": {
"amount": 2000.0,
"country": "US"
}
}]
}],
"time": [{
"spent": [{
"ID": "HR",
"spentamount": {
"amount": 308.91,
"country": "US"
}
}]
}]
}
这是必须迁移到 Postgres 11.5 的查询:
select js.*
from P_P_J r,
json_table(r.P_D_J, '$.*[*]'
COLUMNS(NESTED PATH '$.spent[*]'
COLUMNS(
ID VARCHAR2(100 CHAR) PATH '$.ID',
amount NUMBER(10,4) PATH '$.spentamount.amount',
country VARCHAR2(100 CHAR) PATH '$.spentamount.country'))
) js
结果:
ID, amount, country
HR, 2000.0,US
HR,308.91,US
我这里有两个问题:
$.*[*]
是什么意思?我们如何在 Postgres 中迁移这个查询,以便它直接查看 'spent' 而不是导航 'cost'->'spent' 或 'time' ->'spent'
在 Postgres 中没有 json_table 的直接替代品。您将不得不组合多个调用来分解 JSON 结构。
您没有向我们展示您的预期输出,但据我所知,以下内容应该也是如此:
select e.item ->> 'ID' as id,
(e.item #>> '{spentamount, amount}')::numeric as amount,
e.item #>> '{spentamount, country}' as country
from p_p_j r
cross join jsonb_each(r.p_d_j) as a(key, val)
cross join lateral (
select *
from jsonb_array_elements(a.val)
where jsonb_typeof(a.val) = 'array'
) as s(element)
cross join jsonb_array_elements(s.element -> 'spent') as e(item)
;
JSON 路径表达式 '$.*[*]
表示:遍历所有顶级键,然后遍历其中找到的所有数组元素和嵌套路径 '$.spent[*]'
然后再次遍历那里的所有数组元素。这些步骤反映在到达那里所需的三个 JSON 函数调用中。
使用 Postgres 12,这会更容易一些,因为这可以通过一次调用 jsonb_path_query()
来完成,它也使用 JSON 路径来访问使用非常相似的元素 JSON路径表达式:
select e.item ->> 'ID' as id,
(e.item #>> '{spentamount, amount}')::numeric as amount,
e.item #>> '{spentamount, country}' as country
from p_p_j r
cross join jsonb_path_query(r.p_d_j, '$.*[*].spent[*]') as e(item)
;