如何在T-SQL中有效检查JSON数组中的值

时间:2019-01-22 16:17:41

标签: json tsql sql-server-2017

我想找到一个JSON数组包含一个或多个特定值的多行。有时所有匹配项都需要匹配(AND s,有时只匹配某些(OR s,有时需要两者结合(ANDOR)。

这是在Microsoft SQL Server 2017中。

我尝试在select中执行AS语句,但导致为子查询创建的别名稍后在子查询中无法识别。

下面的例子有效,它看起来没有什么作用,并且具有代码重复。

我怎么只指定一次SELECT VALUE FROM OPENJSON(JsonData, '$.categories'?也许还有其他方法可以做到这一点?

DECLARE @TestTable TABLE
(
  Id int, 
  JsonData nvarchar(4000)
);

INSERT INTO @TestTable
    VALUES 
    (1,'{"categories":["one","two"]}'),
    (2,'{"categories":["one"]}'),
    (3,'{"categories":["two"]}'),
    (4,'{"categories":["one","two","three"]}');

SELECT [Id]
  FROM @TestTable
  WHERE ISJSON(JsonData) = 1
  -- These two lines are the offending parts of code
  AND 'one' in (SELECT VALUE FROM OPENJSON(JsonData, '$.categories'))
  AND 'two' in (SELECT VALUE FROM OPENJSON(JsonData, '$.categories'));

表格式不能更改,尽管我可以添加计算列-如果需要的话。

1 个答案:

答案 0 :(得分:0)

好吧,我不确定这是否对您有帮助...

将嵌套数组转换为派生表以将其用作CTE可能会有所帮助。检查一下:

DECLARE @TestTable TABLE
(
  Id int, 
  JsonData nvarchar(4000)
);

INSERT INTO @TestTable
    VALUES 
    (1,'{"categories":["one","two"]}'),
    (2,'{"categories":["one"]}'),
    (3,'{"categories":["two"]}'),
    (4,'{"categories":["one","two","three"]}');

-这是查询

WITH JsonAsTable AS
(
    SELECT Id 
          ,JsonData
          ,cat.*
    FROM @TestTable tt
    CROSS APPLY OPENJSON(tt.JsonData,'$.categories') cat
)
SELECT *
FROM JsonAsTable

该方法非常接近您自己形成的查询。结果是一个表,每个数组项只有一行。形式Id是重复的分组键,key是数组中的序数位置,而value是您要搜索的单词之一。

在查询中,您可以像在该位置使用任何其他表一样使用JsonAsTable

但是-您将需要重复的FROM OPENJSON谓词...,而不是重复的EXISTS()查询...

一个骇人听闻的解决方案可能是这样的:

SELECT Id
      ,JsonData
      ,REPLACE(REPLACE(REPLACE(JsonData,'{"categories":[','",'),']}',',"'),'","',',')
FROM @TestTable

这将以字符串形式返回所有嵌套数组值,并以逗号分隔。您可以使用LIKE模式进行查询...不过您也可以将其作为计算列返回...