Выходная группа Oracle JSON по ключу

Я динамически генерирую операторы SQL из входного файла и хочу, чтобы выходные данные в формате JSON были сгруппированы по ключу, который я указываю в псевдониме в операторе select.

Входной файл поступает из другой системы и выглядит так:

'abc' AS [x.test1],
'cde' AS [y.test2],
'fgh' AS [y.test3]

В SQL Server у меня есть такой рабочий запрос:

SELECT
    (SELECT 
    'abc' AS [x.test1],
    'cde' AS [y.test2],
    'fgh' AS [y.test3]
    FROM "dbo"."TEST"
    FOR JSON PATH,
    WITHOUT_ARRAY_WRAPPER
) AS RESULT

Он возвращает этот вывод, который сгруппирован по ключу, и он отлично работает:

{"x":{"test1":"abc"},"y":{"test2":"cde","test3":"fgh"}}

Я хочу добиться того же результата с оракулом.

На данный момент я попал сюда:

SELECT 
( 
    SELECT json_object(
            KEY '[x.test1]' IS 'abc',
            KEY '[y.test2]' IS 'cde',
            KEY '[y.test3]' IS 'fgh'
        )
    FROM test
) 
AS RESULT from DUAL;

Проблема в том, что это не группирует мой вывод по ключу:

{"[x.test1]":"abc","[y.test2]":"cde","[y.test3]":"fgh"}
Как настроить Tailwind CSS с React.js и Next.js?
Как настроить Tailwind CSS с React.js и Next.js?
Tailwind CSS - единственный фреймворк, который, как я убедился, масштабируется в больших командах. Он легко настраивается, адаптируется к любому...
LeetCode запись решения 2536. Увеличение подматриц на единицу
LeetCode запись решения 2536. Увеличение подматриц на единицу
Увеличение подматриц на единицу - LeetCode
Переключение светлых/темных тем
Переключение светлых/темных тем
В Microsoft Training - Guided Project - Build a simple website with web pages, CSS files and JavaScript files, мы объясняем, как CSS можно...
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel с методами присоединения и отсоединения
Отношения "многие ко многим" в Laravel могут быть немного сложными, но с помощью Eloquent ORM и его моделей мы можем сделать это с легкостью. В этой...
В PHP
В PHP
В большой кодовой базе с множеством различных компонентов классы, функции и константы могут иметь одинаковые имена. Это может привести к путанице и...
Карта дорог Беладжар PHP Laravel
Карта дорог Беладжар PHP Laravel
Laravel - это PHP-фреймворк, разработанный для облегчения разработки веб-приложений. Laravel предоставляет различные функции, упрощающие разработку...
0
0
75
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Вы можете вложить json_object() вызовы:

SELECT json_object(
  KEY 'x' IS json_object(
    KEY 'test1' IS 'abc'
  ),
  KEY 'y' IS json_object(
    KEY 'test2' IS 'cde',
    KEY 'test3' IS 'fgh'
    )
) 
AS RESULT from DUAL;
РЕЗУЛЬТАТ {"x":{"test1":"abc"},"y":{"test2":"cde","test3":"fgh"}}

Рабочий пример

Или, как вы говорите о группировке, если ваши данные действительно поступают из таблиц, вы можете использовать json_objectagg() и данные таблицы с чем-то вроде:

select json_object(
  'x' value json_object(x.j_key value x.j_value),
  'y' value json_objectagg(y.j_key, y.j_value)
) as result
from x
left join y on y.id = x.id
group by x.id, x.j_key, x.j_value
РЕЗУЛЬТАТ {"x":{"test1":"abc"},"y":{"test2":"cde","test3":"fgh"}}

Рабочий пример

Дело в том, что я получаю несколько строк в этом формате «что-то» AS [key.name], и ​​с этим мне нужно динамически построить оператор выбора. Я могу изменить саму строку, например. KEY 'key.name' IS 'something', но он все равно будет в одной строке, поэтому я не могу иметь части строки в разных частях запроса, если это имеет смысл.

snoopy 11.11.2022 10:31

Откуда вы берете эти строки? Возможно, было бы полезно отредактировать вопрос, чтобы показать ваши необработанные данные и то, как вы их получаете — будь то пользовательский ввод где-то или данные из таблицы и т. д.

Alex Poole 11.11.2022 10:34

Tnx. Я обновил его входным файлом. Дело в том, что я не могу жестко закодировать это «левое соединение y в группе y.id = x.id с помощью x.id, x.j_key, x.j_value», поскольку имена ключей всегда разные. Но это «значение 'x' json_object (значение x.j_key x.j_value)» - это то, что я могу сделать.

snoopy 11.11.2022 10:52

Если входной файл представляет собой текстовый файл со строками типа «abc» AS [x.test1], «cde» AS [y.test2], «fgh» AS [y.test3]», то это означает, что весь процесс разработан для работы с SQLServer и ни с чем другим, поэтому вам следует подумать о более универсальном синтаксисе для описания цели, если вы хотите поддерживать разные СУБД. Функции ORACLE JSON менее автоматизированы, чем функции SQLServer, но позволяют вам делать что-то по-другому, и в основном у вас есть возможность определить ключ значениями столбца, и иногда это позволяет избежать перехода к динамическому SQL, так что воспользуйтесь этим.

p3consulting 11.11.2022 11:31

Если я создам входной файл, чтобы он был таким, знаете ли вы, можно ли сгруппировать вывод по ключу? KEY 'x' IS json_object (KEY 'test1' IS 'abc'), KEY 'y' IS json_object (KEY 'test2' IS 'cde'), KEY 'y' IS json_object (KEY 'test3' IS 'fgh')

snoopy 12.11.2022 16:54
Ответ принят как подходящий
WITH data (expr) AS (
    SELECT q'~'abc' AS [x.test1],'cde' AS [y.test2],'fgh' AS [y.test3]~' FROM DUAL 
),
rdata(expr) AS (
    SELECT regexp_substr(expr,'[^,]+',1,LEVEL) AS expr
    FROM data
    CONNECT BY regexp_substr(expr,'[^,]+',1,LEVEL) IS NOT NULL
), 
exprs AS (
    SELECT expr, regexp_substr(expr, q'~'(.*)'~', 1, 1, 'i', 1) as val, 
        regexp_substr(expr, q'~\[(.*)\]~', 1, 1, 'i', 1) as path 
    FROM rdata 
),
spaths AS (
    SELECT e.*, LEVEL as lvl, regexp_substr(path,'[^\.]+',1,LEVEL) as pitem
    FROM exprs e
    CONNECT BY regexp_substr(path,'[^\.]+',1,LEVEL) IS NOT NULL AND prior val = val AND PRIOR sys_guid() IS NOT NULL
)
SELECT json_object(
    s.pitem VALUE json_objectagg(
        p.pitem VALUE p.val
    )
) AS js
FROM spaths s
    JOIN spaths p ON s.val = p.val AND p.lvl = 2
WHERE s.lvl = 1
GROUP BY s.pitem
;


JS
{"x":{"test1":"abc"}}
{"y":{"test2":"cde","test3":"fgh"}}

CTE предназначен только для преобразования входных «файловых» «строк» ​​в строки, которые мы можем использовать для генерации JSON, как только мы поняли, что преобразование в JSON тривиально.

p3consulting 11.11.2022 14:19

Это выглядит великолепно, tnx! Как вы думаете, возможно ли вывести однострочный код из вашего кода следующим образом {"x":{"test1":"abc"},"y":{"test2":"cde","test3":"fgh" }} ?

snoopy 11.11.2022 15:13

Измените последний запрос, выбрав SELECT LISTAGG( js, ',') WITHIN GROUP(ORDER BY pitem) FROM ( SELECT s.pitem, json_object( s.pitem VALUE json_objectagg( p.pitem VALUE p.val )) AS js FROM spaths s ОБЪЕДИНИТЕ spaths p ON s.val = p.val AND p.lvl = 2, ГДЕ s.lvl = 1 СГРУППИРОВАТЬ ПО s.pitem ) ;

p3consulting 11.11.2022 15:31

Ваш запрос работает нормально, если у вас есть статические значения, подобные этому 'abc' AS [x.test1]. Если вы поместите здесь настоящие утверждения вместо «abc», это не сработает. Например, WITH data (expr) AS (SELECT q'~COUNT * AS [x.test1]~' FROM test_table)

snoopy 12.11.2022 19:13

«Выражение» должно следовать синтаксису, указанному в вашем исходном сообщении: («строка в одинарных кавычках» «AS» «[» «путь» «]» [,])+, если вы меняете правила игры, вы должны изменить синтаксический анализ ... цель состоит в том, чтобы достичь вывода CTE "spaths" (в основном тройки val, lvl, pitem), а затем последний запрос дает решение.

p3consulting 12.11.2022 19:49

Другие вопросы по теме