将多行中的 JSON 对象组合成单个对象

问题描述 投票:0回答:2
CREATE TABLE t(Id int, typee nvarchar(50), jsonStr nvarchar(max));
INSERT INTO t(Id, typee, jsonStr) VALUES
(3786, 'APV', '{"1":1,"3":3,"4":24,"5":95}'),
(3786, 'VN', '{"1":3,"5":25}');

-- Expected result
-- {"APV": {"1":1,"3":3,"4":24,"5":95}, "VN":{"1":3,"5":25} }

SELECT Id,(
    SELECT CASE WHEN typee = 'VN'  THEN jsonStr END AS [VN]
         , CASE WHEN typee = 'VO'  THEN jsonStr END AS [VO]
         , CASE WHEN typee = 'APV' THEN jsonStr END AS [APV]
    FROM t AS x
    WHERE x.Id = t.Id
    FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER
) AS TEST1

FROM t
GROUP BY Id

数据库<>小提琴

我想得到如下输出:

{
  "APV": {
    "1": 1,
    "3": 3,
    "4": 24,
    "5": 95
  },
  "VN": {
    "1": 3,
    "5": 25
  }
}
json sql-server t-sql sql-server-2016 for-json
2个回答
2
投票

FOR JSON
会将字符串视为字符串,即使它代表有效的 JSON。您需要使用
JSON_QUERY
将 JSON 字符串转换为实际的 JSON 对象。需要
MIN
将多行合并为一行:

SELECT Id, (
  SELECT JSON_QUERY(MIN(CASE WHEN typee = 'APV' THEN jsonStr END)) AS [APV]
       , JSON_QUERY(MIN(CASE WHEN typee = 'VN'  THEN jsonStr END)) AS [VN]
       , JSON_QUERY(MIN(CASE WHEN typee = 'VO'  THEN jsonStr END)) AS [VO]
  FROM t AS x
  WHERE x.id = t.id
  FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER
)
FROM t
GROUP BY Id

db<>fiddle 上的演示


1
投票

问题是您正在存储 JSON,然后格式化将其进一步返回为 JSON。您需要存储非 JSON 数据才能按照您想要的方式执行此操作。因此,将其视为字符串似乎更容易:

SELECT t.id,
       '{' + STRING_AGG( '"' +t.typee + '": ' + t.jsonStr,',') WITHIN GROUP (ORDER BY typee) + '}'
FROM t
GROUP BY t.id;

使用

FOR XML PATH

SELECT t1.id,
       '{' + STUFF((SELECT ',"' + t2.typee + '": ' + t2.jsonStr
                    FROM t t2
                    WHERE t2.Id = t1.id
                    FOR XML PATH(N''),TYPE).value('.','nvarchar(MAX)'),1,1,'') + '}'
FROM t t1
GROUP BY t1.id;
© www.soinside.com 2019 - 2024. All rights reserved.