tsql - 在 SQL Server 中,是否可以在不聚合的情况下对行进行透视?
问题描述
这是一个示例:假设每个命令的参数数量有限,我想将参数及其值表示为 named_indexed 列。
--drop table TCommand
--drop table TParam
Create Table TCommand (
CommandID INT,
CommandName NCHAR(20),
Description NVARCHAR(100)
);
Create Table TParam (
CommandID INT,
ParamName NCHAR(20),
ParamValue NCHAR(50)
);
insert into TCommand Values(1, 'C1', 'Desc for command C1')
insert into TCommand Values(2, 'C2', 'Desc for command C2')
insert into TCommand Values(3, 'C3', 'Desc for command C3')
insert into TParam Values (1, 'Pa', 'xa1')
insert into TParam Values (1, 'Pb', 'yb1')
insert into TParam Values (1, 'Pc', 'zc1')
insert into TParam Values (2, 'Px', 'xa2')
insert into TParam Values (2, 'Py', 'yb2')
insert into TParam Values (3, 'Pt', 'xa3')
insert into TParam Values (3, 'Pu', 'yb3')
select tc.*, tp.ParamName, tp.ParamValue
from TCommand tc
join TParam tp on tp.CommandID=tc.CommandID
order by tc.CommandName, tp.ParamName
结果:
CommandID CommandName Description ParamName ParamValue
----------- ----------- -------------------- --------- ----------
1 C1 Desc for command C1 Pa xa1
1 C1 Desc for command C1 Pb yb1
1 C1 Desc for command C1 Pc zc1
2 C2 Desc for command C2 Px xa2
2 C2 Desc for command C2 Py yb2
3 C3 Desc for command C3 Pt xa3
3 C3 Desc for command C3 Pu yb3
这是我想要获得的格式。
CommandID CommandName Description ParamName_1 ParamValue_1 ParamName_2 ParamValue_2 ParamName_3 ParamValue_3
----------- ----------- -------------------- ----------- ------------ ----------- ------------ ----------- ------------
1 C1 Desc for command C1 Pa xa1 Pb yb1 Pc zc1
2 C2 Desc for command C2 Px xa2 Py yb2 NULL NULL
3 C3 Desc for command C3 Pt xa3 Pu yb3 NULL NULL
我应该写什么查询?由于缺少聚合功能(我认为我不需要),早期尝试使用 PIVOT 失败。
提前致谢。
解决方案
您需要在此处创建两个数据透视查询:一个用于 ParamName,另一个用于 ParamValue。在表q1
和q2
派生表中,我只为每个数据透视表选择了所需的列(如果我只q
在两个查询中使用,我会在相关列中获得带有 NULL 的额外行)。
为了能够连接两个查询,您需要一个表示参数位置的列(RowNum
在下面的查询中命名)。
如果数据透视列的每个值都有一个值,则可以使用聚合函数,例如 MIN 或 MAX(忽略 NULL 值并保留单个输入值)。
因此,您可以使用以下查询:
;WITH q AS (
SELECT tp.CommandID,
ROW_NUMBER() OVER (PARTITION BY tp.CommandID ORDER BY tp.ParamName) AS RowNum,
tp.ParamName, tp.ParamValue
FROM dbo.TParam tp
)
SELECT tc.CommandID, tc.CommandName, tc.Description,
x1.ParamName_1, x2.ParamValue_2, x1.ParamName_2, x2.ParamValue_2, x1.ParamName_3, x2.ParamValue_3
FROM dbo.TCommand tc
LEFT JOIN (
SELECT p.CommandID, p.[1] AS ParamName_1, p.[2] AS ParamName_2, p.[3] AS ParamName_3
FROM (SELECT q.CommandID, q.RowNum, q.ParamName FROM q) q1
PIVOT (MAX(ParamName) FOR RowNum IN ([1],[2],[3])) p
) x1 ON x1.CommandID = tc.CommandID
LEFT JOIN (
SELECT p.CommandID, p.[1] AS ParamValue_1, p.[2] AS ParamValue_2, p.[3] AS ParamValue_3
FROM (SELECT q.CommandID, q.RowNum, q.ParamValue FROM q) q2
PIVOT (MAX(ParamValue) FOR RowNum IN ([1],[2],[3])) p
) x2 ON x2.CommandID = tc.CommandID
推荐阅读
- algorithm - 使贪婪算法在欧元硬币子集上失败
- r - Tidyquant:从每个日期(不仅仅是每月)获取跟踪月度回报
- react-native - React Native:以 Modal 显示 FlatList 数据
- ios - 如何在 SceneKit 中简单地旋转 SCNNode?
- html - 如何在标签和输入之间添加空格并使输入在同一行中转到容器的右边缘?
- node.js - nginx 端口重定向发送空 json 对象
- linux - 我在哪里添加 -DCUDA_HOST_COMPILER=/usr/bin/gcc-5 (Pytorch)
- javascript - 没有声明的 ES6 解构赋值
- python - 为什么 numpy.linalg.solve() 对于相同大小的数组有非常量的计算时间?
- vba - 使用传输数据库在数据库之间复制表时出现混乱