【问题标题】:Query JSON data without node in SQLSQL中查询无节点的JSON数据
【发布时间】:2019-04-29 08:19:09
【问题描述】:

我在 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   |
+----+---------+

【问题讨论】:

  • 另外,您需要指定您使用的数据库。
  • 欢迎来到stackoverflow。请花一分钟时间回答tour,尤其是如何How to Askedit 您的问题。
  • SQL Server 2016 或更高版本已内置 JSON 支持。在旧版本中,您将不得不更加努力。
  • 我们使用的是 MS SQL Server 2014

标签: sql json sql-server tsql sql-server-2014


【解决方案1】:

自 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

)

【讨论】:

    【解决方案2】:

    如果你不能使用 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)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2015-07-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-03-29
      • 2020-08-04
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多