如何忽略SQL Server JSON值中的几个属性

时间:2019-06-19 19:54:46

标签: sql json sql-server

我有一个表,其中有一个包含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 个答案:

答案 0 :(得分:7)

使用已更正的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"}

答案 1 :(得分:2)

这是一种完全通用的方法,不需要动态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以EAV(实体-属性-值)的形式在JSON中创建所有属性的列表。这样,就可以轻松排除所有属性,在排除表中可以找到该名称。

由于我们不允许将列的值用作输出列的别名,因此可以使用字符串方法而不是FOR JSON查询来构建JSON。

首先,我使用GROUP BY将最终输出减少为 one-row-per-Id ,然后我使用相关的子查询从Id构建每个ID的JSON。相应的EAV。