我有一个像这样的表,它存储这样的类。这样可能列出了30个类。类别名称的一些示例是“血液出生安全性”,“ CPR培训”,“叉车”。
Name | Class1 | Class1TrainerName | Class2 | Class2TrainerName
------|---------------|---------------------|-----------|---------------
Scott | 3/28/2017 | Casey | 4/19/2017 | David
Jim | | | 2/9/2019 | David
我想把它变成这样。
Name | ClassName | ClassDate | Trainer |
--------|--------------|-------------|----------|
Scott | Class1 | 3/28/2017 | Casey |
Scott | Class2 | 4/19/2017 | David |
Jim | Class2 | 2/9/2019 | David |
如何将table1转换为table2的数据?
答案 0 :(得分:2)
这是一种在this article上详细介绍的方法。
它利用表值构造函数的优点从单个表生成多个行。它还使用APPLY运算符在一次读取中执行此操作。请注意,第一列可以包含将成为您的类名的任何字符串。其他两列是未透视的。
SELECT mt.[Name],
up.ClassName,
up.ClassDate,
up.Trainer
FROM MyTable mt
CROSS APPLY (VALUES('Class1', Class1, Class1TrainerName),
('Class2', Class2, Class2TrainerName),
('Class3', Class3, Class3TrainerName)) AS up(ClassName, ClassDate, Trainer);
答案 1 :(得分:1)
另一种选择是将“动态”取消数据透视,而无需实际使用动态SQL
当然,Luis的解决方案性能更高,但是在这里您不必详述所有列名和数据类型。
示例
Declare @YourTable Table ([Name] varchar(50),[Class1] date,[Class1TrainerName] varchar(50),[Class2] date,[Class2TrainerName] varchar(50))
Insert Into @YourTable Values
('Scott','3/28/2017','Casey','4/19/2017','David')
,('Jim','2/9/2019','David',null,null)
;with cte as (
Select RN
,A.Name
,C.*
,Grp = sum(case when Item not like '%TrainerName' then 1 end) over (Partition by RN Order by Seq)
From (Select *,RN = Row_Number() over (Order by (Select null)) From @YourTable) A
Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
Cross Apply (
Select Item = xAttr.value('local-name(.)', 'varchar(100)')
,Value = xAttr.value('.','varchar(max)')
,Seq = Row_Number() over (Order by (Select null))
From XMLData.nodes('//@*') xNode(xAttr)
Where xAttr.value('local-name(.)','varchar(100)') not in ('Name','RN')
) C
)
Select Name
,ClassName = max(case when Item not like '%TrainerName' then Item end)
,ClassDate = max(case when Item not like '%TrainerName' then Value end)
,Trainner = max(case when Item like '%TrainerName' then Value end)
From cte
Group By RN,Name,Grp
返回
Name ClassName ClassDate Trainner
Scott Class1 2017-03-28 Casey
Scott Class2 2017-04-19 David
Jim Class1 2019-02-09 David