在SQL中查询没有节点的JSON数据

问题描述 投票:1回答:2

我在SQL Server中有一个包含JSON数据的列,其中包含以下值:

+----+-------------------------------------------------------------+
| ID |                           Values                            |
+----+-------------------------------------------------------------+
|  1 | [{"Name":"Test1","Type":null}]                              |
|  2 | [{"Name":"Test2","Type":null}]                              |
|  3 | [{"Name":"Test3","Type":null},{"Name":"Test4","Type":null}] |
|  4 | [{"Name":"Test5","Type":null},{"Name":"Test6","Type":null}] |
+----+-------------------------------------------------------------+

我想在SQL中查询上面的表,并希望结果如下:

+----+---------+
| ID |  Values |
+----+---------+
|  1 | Test1   |
|  2 | Test2   |
|  3 | Test3   |
|  3 | Test4   |
|  4 | Test5   |
|  4 | Test6   |
+----+---------+
sql json sql-server tsql sql-server-2014
2个回答
0
投票

由于您是2014年,如果您对表值函数持开放态度,请考虑以下因素。

厌倦了提取字符串,我修改了一个解析函数来接受两个不相似的分隔符。在这种情况下'"Name":"''"'

Select A.ID 
      ,[Values]=B.RetVal
 From  YourTable A
 Cross Apply [dbo].[tvf-Str-Extract]([Values],'"Name":"','"') B

返回

ID  Values
1   Test1
2   Test2
3   Test3
3   Test4
4   Test5
4   Test6

功能如果感兴趣

CREATE FUNCTION [dbo].[tvf-Str-Extract] (@String varchar(max),@Delimiter1 varchar(100),@Delimiter2 varchar(100))
Returns Table 
As
Return (  

with   cte1(N)   As (Select 1 From (Values(1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) N(N)),
       cte2(N)   As (Select Top (IsNull(DataLength(@String),0)) Row_Number() over (Order By (Select NULL)) From (Select N=1 From cte1 N1,cte1 N2,cte1 N3,cte1 N4,cte1 N5,cte1 N6) A ),
       cte3(N)   As (Select 1 Union All Select t.N+DataLength(@Delimiter1) From cte2 t Where Substring(@String,t.N,DataLength(@Delimiter1)) = @Delimiter1),
       cte4(N,L) As (Select S.N,IsNull(NullIf(CharIndex(@Delimiter1,@String,s.N),0)-S.N,8000) From cte3 S)

Select RetSeq = Row_Number() over (Order By N)
      ,RetPos = N
      ,RetVal = left(RetVal,charindex(@Delimiter2,RetVal)-1) 
 From  (
        Select *,RetVal = Substring(@String, N, L) 
         From  cte4
       ) A
 Where charindex(@Delimiter2,RetVal)>1

)

0
投票

如果您不能使用SQL Server 2016或CLR函数并且您的json相当简单,您可以将其转换为xml并使用SQL Server xml support

;with cte1(id, [values]) as (
    select 1, '[{"Name":"Test1"}]' union all
    select 2, '[{"Name":"Test2"}]' union all
    select 3, '[{"Name":"Test3"},{"Name":"Test4"}]' union all
    select 4, '[{"Name":"Test5"},{"Name":"Test6"}]'
), cte2 as (
    select
        id, cast(replace(replace(replace(replace([values],'[{"','<d '),'"}]','" />'),'"},{"','" />, <d '),'":','=') as xml) as [values]
    from cte1
)
select
    c.id,
    t.c.value('@Name', 'nvarchar(128)') as [Values]
from cte2 as c
    cross apply c.[values].nodes('d') as t(c)
© www.soinside.com 2019 - 2024. All rights reserved.