"expand"/加入 SQL select 通过 JSON 值在 MSSQL
"expand"/join SQL select by JSON values on MSSQL
我遇到了一个问题,我有一个 table,其中有两列包含 JSON 数据。我一直在阅读 Microsoft 关于在 MSSQL 中使用 JSON 的文档,但似乎无法解决我的具体问题。
考虑一下我的 table 中单行的这个相当简单的示例:
我想要实现的是将 LocationsJSON
和 AssigneesJSON
中的值连接到自身上,并希望以这些方式结束:
看微软的文档好像是可以的,但我似乎无法正确处理问题。
JSON 支持已在 SQL Server 2016 中添加。您将无法解析早期版本中的 JSON 字符串。
您可以在 FROM 子句中将 CROSS APPLY
与 return 是 table 的任何函数一起使用,以对函数的结果执行交叉 "join"。在这种情况下,您需要的函数是 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
会 return :
id V1 V2
1 a 1
1 a 2
1 b 1
1 b 2
AND, 想到其他方式,这是较旧的样式 XML
.nodes 方法与 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
最简单的解决方案是
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
我遇到了一个问题,我有一个 table,其中有两列包含 JSON 数据。我一直在阅读 Microsoft 关于在 MSSQL 中使用 JSON 的文档,但似乎无法解决我的具体问题。
考虑一下我的 table 中单行的这个相当简单的示例:
我想要实现的是将 LocationsJSON
和 AssigneesJSON
中的值连接到自身上,并希望以这些方式结束:
看微软的文档好像是可以的,但我似乎无法正确处理问题。
JSON 支持已在 SQL Server 2016 中添加。您将无法解析早期版本中的 JSON 字符串。
您可以在 FROM 子句中将 CROSS APPLY
与 return 是 table 的任何函数一起使用,以对函数的结果执行交叉 "join"。在这种情况下,您需要的函数是 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
会 return :
id V1 V2
1 a 1
1 a 2
1 b 1
1 b 2
AND, 想到其他方式,这是较旧的样式 XML
.nodes 方法与 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
最简单的解决方案是
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