"展开" /加入SQL选择MSSQL上的JSON值

时间:2018-02-07 10:49:26

标签: json tsql azure-sql-database sql-server-2017

我遇到了一个问题,我有一个包含两列包含JSON数据的表。我一直在阅读微软关于在MSSQL中使用JSON的文档,但似乎无法解决我的具体问题。

考虑一下我表中单行的这个相当简单的例子: enter image description here

我希望实现的目标是将LocationsJSONAssigneesJSON的值加入到自身中,并希望最终得到以下内容: enter image description here

在查看Microsoft的文档时似乎有可能,但我似乎无法以正确的方式解决问题。

3 个答案:

答案 0 :(得分:2)

在SQL Server 2016中添加了JSON支持。您将无法在早期版本中解析JSON字符串。

您可以在FROM子句中使用CROSS APPLY和任何返回表的函数来执行与函数结果的交叉“连接”。在这种情况下,您需要的功能是OPENJSON

以下代码:

declare @table table (id int, json1 nvarchar(max), json2 nvarchar(max))

insert into @table values (1,'["a","b"]','["1","2"]')

select id,vals1.value as V1,vals2.value as V2
from @table t 
    cross apply openjson(t.json1) vals1
    cross apply openjson(t.json2) vals2

将返回:

id  V1  V2
1   a   1
1   a   2
1   b   1
1   b   2

答案 1 :(得分:2)

AND,以其他方式考虑旧版XML。带有apply CROSS JOIN的节点方法

with cte as
(
    select 
       Id, Name, LocationJSON,
       cast(ltrim(replace(replace(replace(j.value('.', 'varchar(600)'), '{', ''), '}', ''), '"', ''))  as int)  Locations
    from
    (
       select Id, Name, LocationJSON,
         cast('<X>'+replace(LocationJSON, ',', '</X><X>')+'</X>' as xml) NLocationJSON 
       from table
    )a cross apply NLocationJSON.nodes ('/X') as Location(J)
), cte1 as
(
    select 
       Id, Name, AssigneesJSON,
       ltrim(replace(replace(replace(A.value('.', 'varchar(600)'), '{', ''), '}', ''), '"', ''))   Assignees
    from
    (
       select Id, Name, AssigneesJSON,
         cast('<X>'+replace(AssigneesJSON, ',', '</X><X>')+'</X>' as xml) NAssigneesJSON
       from table
    )a cross apply NAssigneesJSON.nodes ('/X') as Assignees(A)
)

select c.Id, c.Name, 
       c.LocationJSON, c1.AssigneesJSON, 
       c.Locations, c1.Assignees 
from cte c , cte1 c1 -- CROSS JOIN 

结果:

Id  Name    LocationJSON    AssigneesJSON   Locations   Assignees
100 Foo     {"123", "456"}  {"abc", "def"}  123         abc
100 Foo     {"123", "456"}  {"abc", "def"}  123         def
100 Foo     {"123", "456"}  {"abc", "def"}  456         abc
100 Foo     {"123", "456"}  {"abc", "def"}  456         def

答案 2 :(得分:2)

适用于您的方案的最简单的解决方案是

DECLARE @MyTable TABLE  (Id  INT , [Name] VARCHAR(100),LocationsJSON VARCHAR(100) ,AssigneesJSON VARCHAR(100) )
INSERT INTO @MyTable
    SELECT * FROM 
    ( VALUES 
         (100,'Foo','["123","456"]','["abc","def"]' )

    )T (Id  , [Name] ,LocationsJSON  ,AssigneesJSON   )

    SELECT MT.Id, MT.Name,  MT.LocationsJSON ,MT.AssigneesJSON, R1.[value]  as Locations , R2.[value] as Assignees FROM @MyTable MT
    CROSS APPLY
    (
     SELECT * FROM OPENJSON(MT.LocationsJSON)
    )R1
    CROSS APPLY
    (
     SELECT * FROM OPENJSON(MT.AssigneesJSON)
    )R2

输出:

Id  Name    LocationsJSON   AssigneesJSON   Locations   Assignees
-----------------------------------------------------------------
100 Foo     ["123","456"]   ["abc","def"]   123         abc
100 Foo     ["123","456"]   ["abc","def"]   123         def
100 Foo     ["123","456"]   ["abc","def"]   456         abc
100 Foo     ["123","456"]   ["abc","def"]   456         def