Использование T-SQL для извлечения из JSON

Я пытаюсь извлечь данные из следующего JSON и преобразовать данные в «строках» в столбцы.

{
"tables": [
    {
        "name": "PrimaryResult",
        "columns": [
            {
                "name": "timestamp",
                "type": "datetime"
            },
            {
                "name": "message",
                "type": "string"
            },
            {
                "name": "severityLevel",
                "type": "int"
            },
            {
                "name": "FriendlySeverityLevel",
                "type": "string"
            },
            {
                "name": "CycleId",
                "type": "dynamic"
            }
        ],
        "rows": [
            [
                "2024-07-25T12:00:00",
                "Report Started - User: [email protected] MrmClient: 400600 CcID: 000a000b-0000-111c-0a0b-11111a1111a1",
                1,
                "Information",
                "000a000b-0000-111c-0a0b-11111a1111a1"
            ],
            [
                "2024-07-24T12:00:00",
                "Report Started - User: [email protected] MrmClient: 807231 CcID: 000c000d-0000-11c1-0c0d-11111b11111b",
                1,
                "Information",
                "000c000d-0000-11c1-0c0d-11111b11111b"
            ]
        ]
    }
]

}

Вот что я пытаюсь получить в конечном результате:

Использование JSON_VALUE(RawJSON, '$.tables[0].name') дает мне PrimaryResult, но я не могу понять, как извлечь данные из «строк». Я пробовал JSON_VALUE(RawJSON, '$.tables[0].rows[0]'), но он возвращает NULL. Любая помощь будет принята с благодарностью.

В соответствии с руководством по вопросам не публикуйте изображения кода, данных, сообщений об ошибках и т. д. — скопируйте или введите текст в вопрос. Пожалуйста, ограничьте использование изображений для диаграмм или демонстрации ошибок рендеринга, вещей, которые невозможно точно описать с помощью текста.

Dale K 27.07.2024 06:46

rows — это массив массивов. вы хотите что-то вроде этого; SELECT JSON_VALUE(RawJSON, '$.tables[0].rows[0][0]') в качестве отметки времени; SELECT JSON_VALUE(RawJSON, '$.tables[0].rows[0][1]') в качестве сообщения;

A.J.Bauer 27.07.2024 07:10

Прочтите документацию по функции OPENJSON.

siggemannen 27.07.2024 22:11
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
3
100
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

данные

DECLARE @json NVARCHAR(MAX) = '{

    "tables": [

        {

            "name": "PrimaryResult",

            "columns": [

                {

                    "name": "timestamp",

                    "type": "datetime"

                },

                {

                    "name": "message",

                    "type": "string"

                },

                {

                    "name": "severityLevel",

                    "type": "int"

                },

                {

                    "name": "FriendlySeverityLevel",

                    "type": "string"

                },

                {

                    "name": "CycleId",

                    "type": "dynamic"

                }

            ],

            "rows": [

                ["2024-07-25T12:00:00", "Report Started - User: [email protected] MrmClient: 400600 CcID: 000a000b-0000-111c-0a0b-11111a1111a1", 1, "Information", "000a000b-0000-111c-0a0b-11111a1111a1"],

                ["2024-07-24T12:00:00", "Report Started - User: [email protected] MrmClient: 807231 CcID: 000c000d-0000-11c1-0c0d-11111b11111b", 1, "Information", "000c000d-0000-11c1-0c0d-11111b11111b"]

            ]

        }

    ]

}';

используйте OPENJSON с With следующим образом

SELECT *

FROM OPENJSON(@json, '$.tables[0].rows')

WITH (

    timestamp DATETIME '$[0]',

    message NVARCHAR(MAX) '$[1]',

    severityLevel INT '$[2]',

    FriendlySeverityLevel NVARCHAR(MAX) '$[3]',

    CycleId NVARCHAR(MAX) '$[4]'

);

dbfiddle

Ответ принят как подходящий

Если предоставленное содержимое JSON содержит информацию о нескольких таблицах, возможным подходом является динамический оператор. Идея состоит в том, чтобы сгенерировать оператор, который использует OPENJSON() с соответствующими определениями столбцов для каждой таблицы, используя информацию из частей $.tables[*].columns во входном JSON.

Протестируйте JSON с информацией для двух таблиц:

DECLARE @json nvarchar(max) = '{
    "tables": [
        {
        "name": "PrimaryResult",
        "columns": [
            {"name": "timestamp", "type": "datetime"},
            {"name": "message", "type": "string"},
            {"name": "severityLevel", "type": "int"},
            {"name": "FriendlySeverityLevel", "type": "string"},
            {"name": "CycleId", "type": "dynamic"}
        ],
        "rows": [
            ["2024-07-25T12:00:00", "Report Started - User: [email protected] MrmClient: 400600 CcID: 000a000b-0000-111c-0a0b-11111a1111a1", 1, "Information", "000a000b-0000-111c-0a0b-11111a1111a1"],
            ["2024-07-24T12:00:00", "Report Started - User: [email protected] MrmClient: 807231 CcID: 000c000d-0000-11c1-0c0d-11111b11111b", 1, "Information", "000c000d-0000-11c1-0c0d-11111b11111b"]
        ]
        },
        {
        "name": "SecondaryResult",
        "columns": [
            {"name": "timestamp", "type": "datetime"}
        ], 
        "rows": [
            ["2024-07-25T12:00:00"]
        ]
        } 
    ]
}';

Т-SQL:

-- Dynamic statement
DECLARE @stmt nvarchar(max)
; WITH TablesAndColumnsCTE AS (  
   SELECT t.[key] AS TableIndex, c.*
   FROM OPENJSON(@json, '$.tables') t
   CROSS APPLY (
      SELECT 
         [key] AS ColumnIndex, 
         JSON_VALUE([value], '$.name') AS ColumnName, 
         JSON_VALUE([value], '$.type') AS ColumnType
      FROM OPENJSON(t.[value], '$.columns')
   ) c
), StatementsCTE AS (
   SELECT CONCAT(
      N'SELECT * FROM OPENJSON(@json, ''$.tables[', TableIndex, N'].rows'') WITH (',
      STRING_AGG(
         CONCAT(N'[', ColumnName, N'] varchar(max) ''$[', ColumnIndex, N']'''),
         N','
      ) WITHIN GROUP (ORDER BY ColumnIndex),
      N')'
   ) AS Statement
   FROM TablesAndColumnsCTE
   GROUP BY TableIndex
)
SELECT @stmt = STRING_AGG(Statement, N'; ')
FROM StatementsCTE

-- Statement execution
DECLARE @err int  
EXEC @err = sp_executesql @stmt, N'@json nvarchar(max)', @json
IF @err <> 0 PRINT 'Error'

Сформированное заявление на основе тестовых данных опубликовано ниже. Все столбцы определяются как столбцы nvarchar(max), но вы можете легко включить соответствующее выражение CASE и сопоставить типы данных столбцов (datetime, string, int и dynamic в примере) с соответствующими типами данных SQL Server.

SELECT * 
FROM OPENJSON(@json, '$.tables[0].rows') WITH (
   [timestamp] varchar(max) '$[0]',
   [message] varchar(max) '$[1]',
   [severityLevel] varchar(max) '$[2]',
   [FriendlySeverityLevel] varchar(max) '$[3]',
   [CycleId] varchar(max) '$[4]'
);
SELECT * 
FROM OPENJSON(@json, '$.tables[1].rows') WITH (
   [timestamp] varchar(max) '$[0]'
)

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