我正在尝试使用JSON_TABLE将对象的JSON数组映射到关系表列。
Parts数组由指令数组的数组组成。每个指令数组都包含具有三个名称值对的一致名称的对象。名称字段的值始终为“系列”,“功能”或“价格”。这些在数组中并不总是保持一致的顺序。我以为我可以在columns子句中使用过滤条件,以将正确的值映射到正确的列。
WITH STR AS (
select
'
{
"Parts": [
{
"instruction": [
{
"name": "Family",
"value": "AJE",
"type": "0"
},
{
"name": "Feature",
"value": "AJKA",
"type": "0"
},
{
"name": "Price",
"value": "0",
"type": "0"
}
]
},
{
"instruction": [
{
"name": "Feature",
"value": "AJKB",
"type": "0"
},
{
"name": "Family",
"value": "AJA",
"type": "0"
}
]
}
]
}
' JSTR
FROM DUAL)
SELECT JT.*
FROM STR SO,
JSON_TABLE(SO.JSTR, '$.Parts[*].instruction[*]'
COLUMNS ("Family" PATH '$."value"?(@.name == "Family" )',
"Feature" PATH '$."value"?(@.name == "Feature")',
"Price" PATH '$."value"?(@.name == "Price")'
)
)
AS "JT"
显示代码时,它返回五行,所有字段均为空。 我意识到上面的代码是错误的。下面是另一种尝试。这段代码将返回数据(注释掉过滤条件,并对数组索引进行硬编码),但是列数据映射错误。
JSON_TABLE(SO.JSTR, '$.Parts[*]' --ERROR ON ERROR
COLUMNS ("Family" PATH '$.instruction[0]."value"', --?(@.name == "Family" )
"Feature" PATH '$.instruction[1]."value"', --?(@.name == "Feature")
"Price" PATH '$.instruction[2]."value"' --?(@.name == "Price")
)
Family Feature Price
------ ------- -----
AJE AJKA 0
AJKA AJE
I'm trying to return this:
Family Feature Price
------ ------- -----
AJE AJKA 0
AJA AJKB
答案 0 :(得分:0)
更新:ORD应该计算指令,而不是单个值。
要将所需的值放在右列中,请调整路径:
SELECT JT.*
FROM STR SO,
JSON_TABLE(
SO.JSTR, '$.Parts[*].instruction'
COLUMNS (
ord for ordinality,
nested path '$[*]' columns (
Family path '$?(@.name == "Family").value',
Feature path '$?(@.name == "Feature").value',
Price path '$?(@.name == "Price").value'
)
)
)
AS "JT";
ORD FAMILY FEATURE PRICE
1 AJE
1 AJKA
1 0
2 AJKB
2 AJA
现在只需按ORD分组即可:
SELECT ord,
max(family) family,
max(feature) feature,
max(price) price
FROM STR SO,
JSON_TABLE(
SO.JSTR, '$.Parts[*].instruction'
COLUMNS (
ord for ordinality,
nested path '$[*]' columns (
Family path '$?(@.name == "Family").value',
Feature path '$?(@.name == "Feature").value',
Price path '$?(@.name == "Price").value'
)
)
)
AS "JT"
group by ord
order by ord;
ORD FAMILY FEATURE PRICE
1 AJE AJKA 0
2 AJA AJKB
最好的问候,炖阿什顿
答案 1 :(得分:0)
一个选项是确定子查询中Ordinality
的{{1}}值,该子查询将按NESTED PATH '$."Parts"[*]."instruction"[*]'
列值分组的ROW_NUMBER()
函数的排序和{{1} }通过name
和Pivoting
列:
Family
答案 2 :(得分:0)
我希望StackOverflow的人们会始终预先指出他们的Oracle数据库版本。
无论如何,此黑客似乎可以在18c版中使用:
SELECT ord,
max(json_value(jt.Family, '$.value')) family,
max(json_value(jt.Feature, '$.value')) feature,
max(json_value(jt.Price, '$.value')) price
FROM STR SO,
JSON_TABLE(
SO.JSTR, '$.Parts[*].instruction'
COLUMNS (
ord for ordinality,
nested path '$[*]' columns (
Family format json path '$?(@.name == "Family")',
Feature format json path '$?(@.name == "Feature")',
Price format json path '$?(@.name == "Price")'
)
)
)
AS "JT"
group by ord
order by ord;
更好的解决方案是简化JSON并使用PIVOT子句操纵结果:
select family, feature, price
from (
SELECT jt.ord, jt.name, jt.value
from str,
JSON_TABLE(
str.JSTR, '$.Parts[*].instruction'
COLUMNS (
ord for ordinality,
nested path '$[*]' columns (
name varchar2(100) path '$.name',
value varchar2(100) path '$.value'
)
)
)
AS "JT"
)
pivot(max(value) for name in ('Family' as Family, 'Feature' as Feature, 'Price' as Price))
order by ord;