#sql #json #oracle #oracle12c
Вопрос:
У меня есть столбец JSON в таблице persons, в котором хранятся лучшие мероприятия, которые люди проводили в странах, которые они посетили, как это…
{
"countries": [
{
"name": "Ireland",
"bestActivity": {
"name": "Drinking"
}
},
{
"name": "Scotland",
"bestActivity": {
"name": "Dancing"
}
}
]
}
Кто-то еще может быть:
{
"countries": [
{
"name": "Ireland",
"bestActivity": {
"name": "Football"
}
},
{
"name": "England",
"bestActivity": {
"name": "Golf"
}
}
]
}
Я хочу отобрать всех людей, которые посетили Ирландию и с лучшей активностью употребления алкоголя в Ирландии, а также посетили Шотландию и с лучшей активностью употребления алкоголя.
По-настоящему борется. Какие-нибудь советы?
Ответ №1:
Вы можете использовать функцию JSON_EXISTS для фильтрации таблицы на основе описанных вами критериев. Я построил образец запроса ниже, используя структуры JSON, которые вы указали в своем вопросе.
WITH
sample_table (first_name, json_col)
AS
(SELECT 'John', '{
"countries": [
{
"name": "Ireland",
"bestActivity" : {
"name": "Drinking"
},
},
{
"name": "Scotland",
"bestActivity" : {
"name": "Dancing"
}
}
}' FROM DUAL
UNION ALL
SELECT 'Jane', '{
"countries": [
{
"name": "Ireland",
"bestActivity" : {
"name": "Football"
},
},
{
"name": "England",
"bestActivity" : {
"name": "Golf"
}
}
}' FROM DUAL)
SELECT *
FROM sample_table s
WHERE JSON_EXISTS (s.json_col, '$.countries[*]?(@.name == "Scotland")')
AND JSON_EXISTS (
s.json_col,
'$.countries[*]?(@.name == "Ireland" amp;amp; @.bestActivity.name == "Drinking")');
Ответ №2:
JSON_TABLE()
функцию в соответствии с версией вашей базы 12c
данных (для всех субверсий), например
SELECT first_name
FROM t,
JSON_TABLE(jscol, '$.countries[*]'
COLUMNS (
country VARCHAR2(90) PATH '$.name',
bestActivity VARCHAR2(90) PATH '$.bestActivity.name'
)
)
WHERE (country = 'Ireland' AND bestActivity = 'Drinking')
OR country = 'Scotland'
GROUP BY first_name
HAVING COUNT(*)>1
Demo
Вы можете использовать JSON_EXISTS()
функцию, если версия базы данных находится 12cR2
в таком формате
SELECT first_name
FROM t
WHERE JSON_EXISTS(jscol,
'$.countries?(@.name == "Ireland"
amp;amp; @.bestActivity.name == "Drinking")')
AND JSON_EXISTS(jscol,
'$.countries?(@.name == "Scotland")');
Обратите внимание, что запрос следует вызывать после выдачи SET DEFINE OFF
, когда SQL*Plus
используется, чтобы предотвратить amp;amp;
интерпретацию операндов как переменной подстановки.