SQL Server 2016 存储过程中的串联 OPENJSON

Posted

技术标签:

【中文标题】SQL Server 2016 存储过程中的串联 OPENJSON【英文标题】:A concatenation OPENJSON in a SQL Server 2016 stored procedure 【发布时间】:2019-08-26 14:01:01 【问题描述】:

我需要为特定的 UID 组合所有作者。基本字段在另一篇文章的代码中工作。

DECLARE @json NVARCHAR(MAX)

SET @json = '
        "header": 
            "type": "esummary",
            "version": "0.3"
        ,
        "result": 
            "uids": [
                "17784783",
                "19505939",
                "30166592"
            ],
            "17784783": 
                "uid": "17784783",
                "pubdate": "2007 Aug",
                "epubdate": "2007 Jul 20",
                "source": "PLoS Comput Biol",          
                "sortpubdate": "2007/08/01 00:00",
                   "authors": [
                
                    "name": "Yu Y",
                    "authtype": "Author",
                    "clusterid": ""
                ,
                
                    "name": "Wang G",
                    "authtype": "Author",
                    "clusterid": ""
                ,
                
                    "name": "Simha R",
                    "authtype": "Author",
                    "clusterid": ""
                
                 ]          
            ,
            "19505939": 
                "uid": "19505939",
                "pubdate": "2009 Aug 1",
                "epubdate": "2009 Jun 8",
                "source": "Bioinformatics",          
                "sortpubdate": "2009/08/01 00:00"
                  ,
                "authors": [
                
                    "name": "Zang C",
                    "authtype": "Author",
                    "clusterid": ""
                ],

        "30166592": 
            "uid": "30166592",
            "pubdate": "2019 Jan",
            "epubdate": "2018 Aug 30",
            "source": "Oncogene",
             "sortpubdate": "2019/01/01 00:00",
            "authors": [
            
                "name": "Sun J",
                "authtype": "Author",
                "clusterid": ""
            ,
            
                "name": "Cai X",
                "authtype": "Author",
                "clusterid": ""
            ],

        
    
'

我想结束

uid         sortpubdate         epubdate         Authors
-----------------------------------------------------------------------
17784783    2007/08/01 00:00    2007 Jul 20      Yu Y,Wang G,Simha R
19505939    2009/08/01 00:00    2009 Jun 8       Simha R   
30166592    2019/01/01 00:00    2018 Aug 30      Sun J, Cai, X  

我从 OPENJSON syntax in a stored procedure in SQL Server 2016 的 Zohar Peled 那里得到了很好的答复,现在我需要看看我能否完成第一部分。

SELECT [uid], [sortpubdate], [epubdate]
FROM OPENJSON(@json, N'$.result') AS items
CROSS APPLY
-- parse each object in the array
OPENJSON(items.[value])
WITH(
    [uid] nvarchar(max) N'$.uid' ,
    [sortpubdate] nvarchar(max) N'$.sortpubdate',
    [epubdate] nvarchar(max) N'$.epubdate'
) As content
WHERE [key] <> 'uids' -- Get only the relevant content

【问题讨论】:

基本上,您可以使用相同的技术(交叉应用到另一个 openjson)来获取每个uid 的作者姓名和stuff and for xml 的组合以刺激string_agg(已介绍,时尚迟到,仅适用于 2017 版)。 类似于 SELECT stuff(( SELECT '', '' + cast(name as varchar(max)) FROM @json FOR XML PATH('''') ), 1, 2, '' '') 不完全-您需要首先使用另一个openjson(还有另一个cross apply)从json中提取名称-交叉应用的结果应该连接成一个逗号分隔的字符串对于主查询中的每一行。 对不起-听起来我头顶。我一直在谷歌搜索,但找不到答案 【参考方案1】:

你发布的json有点乱,所以我编辑了。

下一个查询应该使用公用表表达式以及stufffor xml 的组合为您提供包括作者姓名在内的结果。

固定的json:

DECLARE @json NVARCHAR(MAX) = 
'
  "header": 
    "type": "esummary",
    "version": "0.3"
  ,
  "result": 
    "17784783": 
      "uid": "17784783",
      "pubdate": "2007 Aug",
      "epubdate": "2007 Jul 20",
      "source": "PLoS Comput Biol",
      "sortpubdate": "2007/08/01 00:00",
      "authors": [
        
          "name": "Yu Y",
          "authtype": "Author",
          "clusterid": ""
        ,
        
          "name": "Wang G",
          "authtype": "Author",
          "clusterid": ""
        ,
        
          "name": "Simha R",
          "authtype": "Author",
          "clusterid": ""
        
      ]
    ,
    "19505939": 
      "uid": "19505939",
      "pubdate": "2009 Aug 1",
      "epubdate": "2009 Jun 8",
      "source": "Bioinformatics",
      "sortpubdate": "2009/08/01 00:00",
      "authors": [
        
          "name": "Zang C",
          "authtype": "Author",
          "clusterid": ""
        
      ]
    ,
    "30166592": 
      "uid": "30166592",
      "pubdate": "2019 Jan",
      "epubdate": "2018 Aug 30",
      "source": "Oncogene",
      "sortpubdate": "2019/01/01 00:00",
      "authors": [
        
          "name": "Sun J",
          "authtype": "Author",
          "clusterid": ""
        ,
        
          "name": "Cai X",
          "authtype": "Author",
          "clusterid": ""
        
      ]
    ,
    "uids": [
      "17784783",
      "19505939",
      "30166592"
    ]
  
'; 

使用公用表表达式从 json 中提取值:

WITH CTE AS
(
    SELECT  [uid], 
            [sortpubdate], 
            [epubdate], 
            [name]
    FROM OPENJSON(@json, N'$.result') AS items
    CROSS APPLY
    -- parse each object in the array
    OPENJSON(items.[value])
    WITH(
        [uid] nvarchar(max) N'$.uid' ,
        [sortpubdate] nvarchar(max) N'$.sortpubdate',
        [epubdate] nvarchar(max) N'$.epubdate',
        -- Note the AS JSON on the next row - will not work without it!
        [authors] nvarchar(max) N'$.authors'  AS JSON 
    ) As content
    CROSS APPLY 
    OPENJSON([authors])
    WITH ([name] nvarchar(max) N'$.name') 
    As authorsNames
    WHERE items.[key] <> 'uids' -- Get only the relevant content
)

并使用stufffor xml 查询cte:

SELECT  DISTINCT [uid], 
        [sortpubdate], 
        [epubdate], 
        STUFF((
            SELECT ',' + [name] 
            FROM CTE As t1
            WHERE t1.[uid] = t0.[uid]
            FOR XML PATH('')
        ), 1, 1, '') As authors
FROM CTE As t0

结果:

uid         sortpubdate         epubdate        authors
17784783    2007/08/01 00:00    2007 Jul 20     Yu Y,Wang G,Simha R
19505939    2009/08/01 00:00    2009 Jun 8      Zang C
30166592    2019/01/01 00:00    2018 Aug 30     Sun J,Cai X

【讨论】:

太棒了 - 这太棒了 我已经编辑了我的答案给你一个完整的解决方案。 这是一个超越的努力

以上是关于SQL Server 2016 存储过程中的串联 OPENJSON的主要内容,如果未能解决你的问题,请参考以下文章

使用 SQL Server 中的存储过程动态更新

我应该如何使用 sql server 中的存储过程将列名存储在变量中?

SQL Server 2005 中的复杂串联

如何将 SQL Server 存储过程迁移到 Mysql [关闭]

在 SQL Server 2016 中调试一个关于存储过程执行的奇怪场景

如何在 SQL Server 存储过程中将“101,102,103”转为“101”、“102”、“103”