在 SQL 服务器中构建和分组 JSON 对象

Building and Grouping JSON Object in SQL Server

我有以下 table,我正在尝试将这些行组合成 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数组元素通常涉及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"}

您可以使用 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;

这确实有重新查询 table 的缺点。为了提高性能,您可以使用 STRING_AGG 手动构造 JSON(不幸的是,SQL 服务器没有 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;