【问题标题】:Sql Query to get an array having no column name in json resultSql Query获取json结果中没有列名的数组
【发布时间】:2023-04-04 21:38:01
【问题描述】:

我有一个包含以下字段的表格

 Id     RequestId     CategoryId
 1      112           1
 2      123           1
 3      123           2

SELECT      R.RequestId,
            (SELECT RC.CategoryId FROM Request RC WHERE RC.Id = R.Id FOR JSON AUTO) AS Categories
FROM        Request R

上面的查询返回的数据如下所述

 RequestId     Categories
 112           [{"CategoryId":"1"}]
 123           [{"CategoryId":"1"},{"CategoryId":"2"}]

但是,我希望列名 CategoryId 不应该为 json 数组中的每个项目重复。因此,我的预期结果是:

 RequestId     Categories
 112           ["1"]
 123           ["1","2"]

【问题讨论】:

    标签: sql arrays json sql-server tsql


    【解决方案1】:

    被使用:SQL to JSON - array of objects to array of values in SQL 2016

    create table Request (
      Id int,
      RequestId int,
      CategoryId int
    )
    GO
    
    insert into Request (Id,RequestId,CategoryId) values
    ( 1,      112,           1),
    ( 2,      123,           1),
    ( 3,      123,           2);
    GO
    
    SELECT distinct R.RequestId,
                (
    SELECT  
      JSON_QUERY('[' + STUFF(( SELECT ',' + '"' + convert(varchar(10), RC.CategoryId) + '"' 
    FROM Request RC
    WHERE RC.RequestId = R.RequestId
    FOR XML PATH('')),1,1,'') + ']' ) Categories  
    FOR JSON PATH , WITHOUT_ARRAY_WRAPPER 
                ) AS Categories
    FROM Request R
    GO
    
    请求ID |类别 --------: | :------------------------ 112 | {“类别”:[“1”]} 123 | {“类别”:[“1”,“2”]}
    SELECT  distinct R.RequestId,
    
    JSON_QUERY(
                (
    SELECT  
      JSON_QUERY('[' + STUFF(( SELECT ',' + '"' + convert(varchar(10), RC.CategoryId) + '"' 
    FROM Request RC
    WHERE RC.RequestId = R.RequestId
    FOR XML PATH('')),1,1,'') + ']' ) Categories  
    FOR JSON PATH , WITHOUT_ARRAY_WRAPPER 
                )
    , '$.Categories' )
    FROM Request R
    GO
    
    请求ID | (无列名) --------: | :--------------- 112 | [“1”] 123 | ["1","2"]

    db小提琴here

    【讨论】:

    • 感谢您的回答。但是,当数据量很大时,STUFF 会使查询执行速度非常慢。有什么想法吗?
    【解决方案2】:

    据我所知,您需要自己聚合字符串,然后将其转换为 json。比如在Sql Server 2017中可以使用STRING_AGG

    select
        t.RequestId,
        concat('[',string_agg(t.CategoryId, ','),']') as Categories
    from Table1 as t
    group by
        t.RequestId
    

    sql fiddle demo

    如果您需要您的数组值是字符串而不是整数,那么您需要手动添加 " 字符,并且您可能还想使用 STRING_ESCAPE 以便安全地转换特殊字符:

    select
        t.RequestId,
        concat('[',string_agg(concat('"', string_escape(t.CategoryId, 'json'),'"'),','),']') as Categories
    from Table1 as t
    group by
        t.RequestId
    

    sql fiddle demo

    在 Sql Server 的年度版本中,您可以使用 xml 技巧或创建自定义 clr 聚合。

    【讨论】:

      【解决方案3】:

      可以使用REPLACE实现:

       declare @test table ([Id] int, [RequestId] int, [CategoryId] int)
       insert into @test values
         (1, 112, 1)
       , (2, 123, 1)
       , (3, 123, 2)
      
          SELECT      R.RequestId,
                      json_query(replace(replace((SELECT RC.CategoryId FROM @test RC WHERE RC.Id = R.Id FOR JSON AUTO), '{"CategoryId":', '"'), '}','"'))  AS Categories
          FROM        @test R
      

      【讨论】:

        【解决方案4】:

        样品表

        SELECT Id,RequestId,CategoryId INTO #Request FROM ( values
        ( 1,      112,           '1'),
        ( 2,      123,           '1'),
        ( 3,      123,           '2'))v(Id,RequestId,CategoryId)
        ;
        

        您可以执行递归查询

         WITH S AS (
            SELECT RequestId,CategoryId,ROW_NUMBER()OVER(Partition BY RequestId ORDER BY CategoryId DESC) _LP FROM  #Request
            )
            , C AS (
            SELECT s.RequestId,JSON_MODIFY('[]','append $',s.CategoryId)w,s._lp
            FROM (SELECT RequestId,MAX(_LP)_MLP FROM S GROUP BY RequestId) S1
            INNER JOIN S ON s.RequestId=s1.RequestId AND s._LP=s1._MLP
            union ALL
            SELECT s.RequestId,JSON_MODIFY(c.w,'append $',s.CategoryId)w,s._lp
            FROM  S
            inner join C ON s.RequestId=c.RequestId and s._LP=c._lp-1
            )
            SELECT RequestId,W Categories FROM C WHERE _LP=1 
        

        您将收到结果:

        RequestId   Categories
        ----------- --------------------
        112         ["1"]
        123         ["1","2"]
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-12-26
          • 2020-02-05
          • 1970-01-01
          • 1970-01-01
          • 2011-09-14
          相关资源
          最近更新 更多