Просто еще один вариант, который «динамически» отключает ваши данные БЕЗ фактического использования динамического SQL
Конечно, решение Луиса было бы более производительным, но здесь вам не нужно детализировать все имена столбцов и типы данных.
Пример
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