Cha*_*ert 5 sql-server sql-server-2016
我有一个资产表和一个属性表,其中属性是简单的键/值对。
DECLARE @Asset TABLE(AssetID INT)
INSERT @Asset VALUES (1)
DECLARE @Att TABLE (AssetID INT, Name NVARCHAR(100), Val NVARCHAR(100))
INSERT @Att VALUES (1, 'height', '100px'), (1, 'width', '200px')
Run Code Online (Sandbox Code Playgroud)
我想编写一个按资产分组的查询,并包含一个包含所有属性的 JSON 表示形式的列。例如:
AssetID Attributes
------------ -----------------------------------------------
1 {"height":"100px","width":"200px"}
Run Code Online (Sandbox Code Playgroud)
如何编写查询以使属性名称值成为结果 JSON 对象中的键?当我使用 FOR JSON PATH 时,键是列名称:
AssetID Attributes
------------ -----------------------------------------------
1 {"height":"100px","width":"200px"}
Run Code Online (Sandbox Code Playgroud)
返回...
AssetID Attributes
------------ -----------------------------------------------
1 [{"Name":"height","Val":"100px"},{"Name":"width","Val":"200px"}]
Run Code Online (Sandbox Code Playgroud)
不确定是否有任何本机JSON方法来获取列数据,Key如JSON. Alias名称将被转换为 中的键值JSON。
所以这是我的尝试
您需要对数据进行透视以获得所需的键值对格式JSON
如果key是静态的那么
SELECT
AssetID,
(
SELECT Max(CASE WHEN NAME = 'height' THEN Val END) AS height,
Max(CASE WHEN NAME = 'width' THEN Val END) AS width
FROM @Att att
WHERE att.AssetID = asset.AssetID
FOR JSON path, WITHOUT_ARRAY_WRAPPER
) Attributes
FROM @Asset asset
Run Code Online (Sandbox Code Playgroud)
WITHOUT_ARRAY_WRAPPER是默认删除子句输出周围JSON的方括号FOR JSON
结果:
+---------+--------------------------------------+
| AssetID | Attributes |
+---------+--------------------------------------+
| 1 | [{"height":"100px","width":"200px"}] |
+---------+--------------------------------------+
Run Code Online (Sandbox Code Playgroud)
由于键可以是任何我们需要使用动态查询来透视数据的内容
对于演示,我已将表变量更改为临时表
CREATE TABLE #Asset
(
AssetID INT
)
INSERT #Asset
VALUES (1)
CREATE TABLE #Att
(
AssetID INT,
NAME NVARCHAR(100),
Val NVARCHAR(100)
)
INSERT #Att
VALUES (1,'height','100px'),
(1,'width','200px')
DECLARE @col VARCHAR(8000)= ''
SET @col = (SELECT ',Max(CASE WHEN NAME = ''' + NAME
+ ''' THEN Val END) as ' + Quotename(NAME)
FROM #Att
FOR xml path(''))
SET @col = Stuff(@col, 1, 1, '')
EXEC ('
SELECT
AssetID,
(
SELECT '+@col+'
FROM #Att att
WHERE att.AssetID = asset.AssetID
FOR JSON path, WITHOUT_ARRAY_WRAPPER
) Attributes
FROM #Asset asset')
Run Code Online (Sandbox Code Playgroud)
结果:
+---------+--------------------------------------+
| AssetID | Attributes |
+---------+--------------------------------------+
| 1 | [{"height":"100px","width":"200px"}] |
+---------+--------------------------------------+
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
10824 次 |
| 最近记录: |