Как игнорировать несколько свойств в значении JSON SQL Server - PullRequest
0 голосов
/ 19 июня 2019

У меня есть таблица, в которой есть столбец с данными JSON.Каждый объект JSON в каждом столбце имеет много свойств.У меня есть другая таблица, имя свойства которой есть не у всех, кроме нескольких.

Мне нужно написать запрос для выбора данных JSON из таблицы, но JSON не должен содержать свойства, которые есть во второй таблице.Например, ниже приведена таблица jSON.

Id      Person
1       {FirstName:"test", LastName: "test", Email: "test@test.abc"}
2       {FirstName:"syx", LastName: "ave", Email: "yyeyd@test.abc"}

Вторая таблица с именем свойства:

ExclusionId   ExcludedProperty
1              Email

Запрос должен объединить эти две таблицы, и результат должен быть

 Id          Person
  1       {FirstName:"test", LastName: "test"}
  2       {FirstName:"syx", LastName: "ave"}

Ответы [ 2 ]

7 голосов
/ 19 июня 2019

С исправленным JSON вы можете использовать JSON_MODIFY() и установить желаемое значение на NULL

Пример

Declare @YourTable Table ([Id] int,[Person] varchar(500))
Insert Into @YourTable Values 
 (1,'{"FirstName":"test", "LastName": "test", "Email": "test@test.abc"}')
,(2,'{"FirstName":"syx", "LastName": "ave", "Email": "yyeyd@test.abc"}')

Select A.ID 
      ,NewValue = JSON_MODIFY([Person],'$.Email',null)
 From  @YourTable A

Возвращает

ID  NewValue
1   {"FirstName":"test", "LastName": "test"}
2   {"FirstName":"syx", "LastName": "ave"}
2 голосов
/ 24 июня 2019

Это полностью общий подход без необходимости динамического SQL:

--a mockup to simulate your issue
--credits to John Cappelletti for the mockup-code
DECLARE @YourTable TABLE (Id INT,Person NVARCHAR(500))
INSERT INTO @YourTable VALUES 
 (1,'{"FirstName":"test", "LastName": "test", "Email": "test@test.abc"}')
,(2,'{"FirstName":"syx", "LastName": "ave", "Email": "yyeyd@test.abc"}');

DECLARE @ExcludeProperties TABLE (Id INT,PropName VARCHAR(500))
INSERT INTO @ExcludeProperties VALUES (1,'Email');

- запрос

WITH cte AS
(
    SELECT t.Id
          ,JsonValues.[key] AS PropName
          ,JsonValues.[value] AS PropValue
    FROM @YourTable t
    CROSS APPLY OPENJSON(t.Person) jsonValues
    WHERE JsonValues.[key] COLLATE Latin1_General_CI_AS NOT IN(SELECT excl.PropName COLLATE Latin1_General_CI_AS FROm @ExcludeProperties excl)
)
SELECT cte.Id
      ,CONCAT('{',
      STUFF((
        SELECT CONCAT(',"',cte2.PropName,'":"',cte2.PropValue,'"')
        FROM cte cte2
        WHERE cte2.Id=cte.Id 
        FOR XML PATH('')
      ),1,1,'')
      ,'}')
FROM cte
GROUP BY cte.Id;

Идея вкратце:

Сначала мы используем CTE для создания списка всех свойств в вашем JSON как EAV (Entity-Attribute-Value). С этим легко избавиться от всех атрибутов, имя которых находится в вашей таблице исключений.

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

Сначала я использую GROUP BY, чтобы уменьшить конечный результат до one-row-per-Id , и я использую коррелированный подзапрос для построения JSON для Id из соответствующих EAV.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...