Это полностью общий подход без необходимости динамического 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.