【问题标题】:Building and Grouping JSON Object in SQL Server在 SQL Server 中构建和分组 JSON 对象
【发布时间】:2021-10-20 19:02:43
【问题描述】:

我有下表,我正在尝试将这些行组合成 JSON 对象。

Username AccessKeys Marker
user1 {"Account":"1","Checking":"0001","Loan":"null","Savings":0} New
user2 {"Account":"2","Checking":"0001","Loan":"null","Savings":0} New
user2 {"Account":"3","Checking":"0001","Loan":"null","Savings":0} New

结果应该是这样的。

Username JSON
user1 {"Accounts": [{"Account": "1","Checking": "0001","Loan": null,"Savings": 0}],"Marker": "New"}
user2 {"Accounts": [{"Account": "1","Checking": "0001","Loan": null,"Savings": 0},{"Account": "2","Checking": "0001","Loan": null,"Savings": 0}],"Marker": "New"}

我目前的查询是这样的。我已经能够做到这一点,但不知道如何从这里开始。

SELECT
     Username
    ,Accounts = (
        SELECT
             Account
            ,Checking
            ,Loan
            ,Savings
        FROM dbo.Accounts A1
        WHERE A1.Account= A2.Account
        FOR JSON PATH, WITHOUT_ARRAY_WRAPPER 
     )
FROM
    dbo.Accounts A2
GROUP BY
     Accounts
    ,Username
;

提前致谢!

解决方案

这是我的最后一个查询。

SELECT
  Username
 ,(
      SELECT
           Accounts = JSON_QUERY((
           SELECT AK.*
           FROM
                dbo.Accounts A2
                CROSS APPLY OPENJSON(Accounts) WITH (
                      Account nvarchar(10)
                     ,Checking nvarchar(10)
                     ,Loan nvarchar(10)
                     ,Savings int
                ) AK
           WHERE A2.Username = A1.Username
           FOR JSON PATH
           ))
           ,'New' Marker
      FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
 ) JSON
FROM dbo.Accounts A1
GROUP BY Username
;

【问题讨论】:

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


    【解决方案1】:

    使用 SQL Server 创建 JSON 数组元素通常涉及到json_query,例如...

    select
      Username,
      [JSON] = (
        select
          [Accounts] = json_query((
            select AK.*
            from dbo.Accounts A2
            cross apply openjson(AccessKeys) with (
              Account nvarchar(10),
              Checking nvarchar(10),
              Loan nvarchar(10),
              Savings int
            ) AK
            where A2.Username = A1.Username
            for json path
          )),
          [Marker]
        for json path, without_array_wrapper
      )
    from dbo.Accounts A1
    group by Username, Marker;
    

    这会产生结果...

    Username JSON
    user1 {"Accounts":[{"Account":"1","Checking":"0001","Loan":"null","Savings":0}],"Marker":"New"}
    user2 {"Accounts":[{"Account":"2","Checking":"0001","Loan":"null","Savings":0},{"Account":"3","Checking":"0001","Loan":"null","Savings":0}],"Marker":"New"}

    【讨论】:

    • 我最终使用了您的查询版本。我用头撞墙好几个小时。非常感谢!
    【解决方案2】:

    您可以使用ROOT 添加根属性,并删除WITHOUT_ARRAY_WRAPPER,因为您实际上需要这里的数组。

    SELECT
         Username
        ,JSON = (
            SELECT
                 Account
                ,Checking
                ,Loan
                ,Savings
            FROM dbo.Accounts A1
            WHERE A1.Username = A2.Username
            FOR JSON PATH, ROOT('Accounts')
         )
    FROM
        dbo.Accounts A2
    GROUP BY
         A2.Username;
    

    这确实有重新查询表的缺点。为了提高性能,您可以使用 STRING_AGG 手动构造 JSON(不幸的是,SQL Server 没有 JSON_AGG)。

    SELECT
         Username
        ,JSON = (
           SELECT Accounts = JSON_QUERY('[' + STRING_AGG(
             (SELECT
                 A.Account
                ,A.Checking
                ,A.Loan
                ,A.Savings
             FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
            ), ',') + ']')
           FOR JSON PATH)
    FROM
        dbo.Accounts A
    GROUP BY
         A.Username;
    

    【讨论】:

    • 对不起,这是没有 STRING_AGG 函数的 SQL Server 2016。
    猜你喜欢
    • 1970-01-01
    • 2021-11-30
    • 2018-06-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-02
    • 2021-10-10
    • 1970-01-01
    相关资源
    最近更新 更多