Как я могу преобразовать данные столбцов в строки данных SQL? - PullRequest
0 голосов
/ 15 апреля 2019

У меня есть такая таблица, в которой хранятся такие классы.Вероятно, есть 30 классов, которые перечислены таким образом.Некоторыми примерами названий классов являются «Безопасность на крови», «Обучение СЛР», «Вилочный погрузчик».

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?

Ответы [ 2 ]

2 голосов
/ 15 апреля 2019

Этот метод подробно описан в этой статье .

Он использует преимущество конструктора табличных значений для генерации нескольких строк из одной. Он также использует оператор APPLY, чтобы сделать это за одно чтение. Обратите внимание, что первый столбец может содержать любую строку, которая станет вашим именем класса. Другие 2 столбца - это те, которые не развернуты.

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 голос
/ 16 апреля 2019

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