Azure SQL:以列为键生成 JSON

Azure SQL: generate JSON with column as key

我的 sql 服务器 table

中有以下数据
Name Value ValueHash
country aaa zzz
lastname ccc yyy
email a@a.com xxx
firstName bbb www

我想要下面的 Json 使用 sql 查询

{
    "lastname": {
      "value": "ccc",
      "valueHash": "yyy"
    },
    "email": {
      "value": "a@a.com",
      "valueHash": "xxx"
    },
    "firstName": {
      "value": "bbb",
      "valueHash": "www"
    },
    "country": {
      "value": "aaa",
      "valueHash": "zzz"
    }
}

我可以提出以下查询

select Value as 'value', ValueHash as 'valueHash'  from user
where id=752594
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER

哪个returns

    {
      "value": "ccc",
      "valueHash": "yyy"
    },
    {
      "value": "a@a.com",
      "valueHash": "xxx"
    },
    {
      "value": "bbb/T1B+4nzpVhb0M",
      "valueHash": "www"
    },
    {
      "value": "aaa",
      "valueHash": "zzz"
    }

尝试了 generate json with column value as json dict key 的解决方案,但遇到编译器错误。

有人可以帮我解决这个问题吗? TIA

这会产生类似的结果。告诉 SQL 服务器不要对内部值使用数组包装器会导致它转义结果:

WITH YourTable AS(
    SELECT *
    FROM (VALUES('country','aaa','zzz'),
                ('lastname','ccc','yyy'),
                ('email','a@a.com','xxx'),
                ('firstName','bbb','www'))V(Name,Value,ValueHash))
SELECT (SELECT value,
               ValueHash
        WHERE YT.Name = 'lastname'
        FOR JSON PATH) AS lastname,
       (SELECT value,
               ValueHash
        WHERE YT.Name = 'email'
        FOR JSON PATH) AS email,
       (SELECT value,
               ValueHash
        WHERE YT.Name = 'firstName'
        FOR JSON PATH) AS firstName,
       (SELECT value,
               ValueHash
        WHERE YT.Name = 'country'
        FOR JSON PATH) AS country
FROM YourTable YT
FOR JSON PATH, WITHOUT_ARRAY_WRAPPER;

很遗憾,SQL服务器没有JSON_AGGJSON_OBJECT_AGG。所以你需要用 STRING_AGGSTRING_ESCAPE

来破解它
SELECT
  '{' +
  STRING_AGG(
  CONCAT(
    '"',
    STRING_ESCAPE(u.Name, 'json'),
    '":',
    v.json
  ), ','
 ) + '}'
FROM [user] u
CROSS APPLY (
    SELECT
      u.Value AS value,
      u.ValueHash AS valueHash
    FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
) v(json)
WHERE u.id = 752594;

db<>fiddle

如果您曾经想要 return 多个对象,假设您在 table 中有一列 id,正如您在 WHERE 中暗示的那样条款,你可以这样做:

DECLARE @t TABLE (id INT,
                  Name VARCHAR(100),
                  Value VARCHAR(100),
                  ValueHash VARCHAR(100));
INSERT @t (id, Name, Value, ValueHash)
VALUES (1, 'country', 'aaa', 'zzz'),
       (1, 'lastname', 'ccc', 'yyy'),
       (1, 'email', 'a@a.com', 'xxx'),
       (1, 'firstName', 'bbb', 'www'),
       (2, 'country', 'aaa2', 'zzz2'),
       (2, 'lastname', 'ccc2', 'yyy2'),
       (2, 'email', 'a2@a2.com', 'xxx2'),
       (2, 'firstName', 'bbb2', 'www2');


SELECT (SELECT Value, ValueHash
        FROM @t
        WHERE id = t1.id AND Name = 'lastname'
       FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER) lastname,
       (SELECT Value, ValueHash
        FROM @t
        WHERE id = t1.id AND Name = 'email'
       FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER) email,
       (SELECT Value, ValueHash
        FROM @t
        WHERE id = t1.id AND Name = 'firstName'
       FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER) firstName,
       (SELECT Value, ValueHash
        FROM @t
        WHERE id = t1.id AND Name = 'country'
       FOR JSON AUTO, WITHOUT_ARRAY_WRAPPER) country
FROM @t t1
WHERE t1.Name = 'lastname'
FOR JSON PATH;

请注意,与 Larnu 的解决方案一样,它也会转义 ValueValueHash 的值。