Ayo*_*rus 1 sql t-sql sql-server pivot sql-server-2008
我正在尝试创建两列PIVOT查询.结构如下:
DECLARE @Tmp TABLE( Id1 int, Id2 int, Name nvarchar(20), Val1 int, Val2 nvarchar(10))
Run Code Online (Sandbox Code Playgroud)
使用以下虚拟数据:
INSERT INTO @Tmp VALUES(1,10,'A',2,'str1'), (1,11,'B',2,'str2'),
(2,10,'A',3,'str3'),(3,11,'B',4, null),(4,11,'B',5,'str4'),(4,10,'A',5,null)
Run Code Online (Sandbox Code Playgroud)
我想要实现的是具有2个不同值(Val1, Val2)的PIVOT查询.我确实尝试了以下查询,但是,由于Val2是a ,因此无法对结果中的值进行分组nvarchar
SELECT * FROM
(SELECT Id1, Name, Val1, Val2, Name +'_Val2' AS ColVal2 FROM @Tmp) AS tb
PIVOT(MIN(Val1) FOR Name IN([A],[B])) pv
PIVOT(MIN(Val2) FOR ColVal2 IN([A_Val2],[B_Val2])) pv2
-- GROUP BY could go here ...
Run Code Online (Sandbox Code Playgroud)
重要的是要查询将是动态的,因为值Name不是固定的,即Id1可以与n相关Id2
所需的输出应如下所示:
Id1 A B A_Val2 B_Val2
1 2 2 str1 str2
2 3 NULL str3 NULL
3 NULL 4 NULL NULL
4 5 5 NULL str4
Run Code Online (Sandbox Code Playgroud)
任何建议将不胜感激
使用条件聚合更容易实现
SELECT Id1,
[A] = Min(CASE WHEN NAME = 'a' THEN Val1 END),
[B] = Min(CASE WHEN NAME = 'b' THEN Val1 END),
[A_Val2] = Min(CASE WHEN NAME = 'a' THEN Val2 END),
[B_Val2] = Min(CASE WHEN NAME = 'b' THEN Val2 END)
FROM @Tmp
GROUP BY Id1
Run Code Online (Sandbox Code Playgroud)
这是一个动态版本(将表变量更改为临时表)
declare @col_list varchar(max) = '',@sql varchar(max)
set @col_list = stuff((select distinct ','+quotename(Name),',' ,quotename(Name+'_Val2') from #Tmp for xml path('')),1,1,'')
--select @col_list
set @sql = '
SELECT *
FROM (SELECT Id1,
col,
val
FROM #Tmp
CROSS apply (VALUES (Cast(Val1 AS VARCHAR(50)),NAME),
(Val2,NAME + ''_Val2'')) cs (val, col))a
PIVOT (Max(val)
FOR col IN ('+@col_list+')) pv'
exec (@sql)
Run Code Online (Sandbox Code Playgroud)