Комбинированная полу-транспонирование данных - PullRequest
2 голосов
/ 17 апреля 2019

Рассмотрим следующий запрос:

DECLARE @T1 TABLE(
  [Id] [int] IDENTITY(1,1) NOT NULL,
  [Data] VARCHAR(100),
  [Column1] VARCHAR(100),
  [Column2] VARCHAR(100),
  [Column3] VARCHAR(100));

INSERT INTO @T1([Data],[Column1],[Column2],[Column3])
    VALUES
        ('Data1','C11','C21','C31'),
        ('Data2','C12','C22','C32'),
        ('Data3','C13','C23','C33'),
        ('Data4','C14','C24','C34'),
        ('Data5','C15','C25','C35');

SELECT * FROM @T1;

Вывод выглядит следующим образом:

enter image description here

Теперь мы хотим сохранить столбец «Данные» и для каждого другого столбца складывать результат выбора для этого столбца в финальную таблицу. Другими словами, следующий запрос производит вывод:

-- I am looking for a better solution than below!
DECLARE @output TABLE([Data] VARCHAR(100),[Column] VARCHAR(100));

INSERT INTO @output([Data],[Column])
    (SELECT [Data],[Column1] FROM @T1
      UNION
    SELECT [Data],[Column2] FROM @T1
      UNION
    SELECT [Data],[Column3] FROM @T1)

SELECT * FROM @output

Что может быть лучше, чем выше, для получения конечного результата? Поскольку число столбцов увеличивается, это означает, что для каждого нового столбца мне нужно иметь отдельную вставку, которая кажется грубым решением. В идеале я ищу решение, основанное на сводных данных, но я не смог придумать что-то конкретное.

enter image description here

Ответы [ 2 ]

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

Конечно, решение Йогеша будет более производительным.Однако, так как ваши столбцы расширяются со временем, вот один подход, который «динамически» разворачивает ваши данные БЕЗ , фактически используя Dynamic SQ:

Пример

Select A.[Data]
      ,C.*
 From  @T1 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(100)')
                 From  XMLData.nodes('//@*') xNode(xAttr)
                 Where xAttr.value('local-name(.)','varchar(100)') not in ('Id','Data','Other-Columns','To-Exclude')
             ) C

Возвращает

enter image description here

1 голос
/ 17 апреля 2019

Я часто использую apply вместо union:

select t1.data, t2.cols
from @t1 t1 cross apply
     ( values ([column1]), ([column2]), ([column3]) ) t2(cols);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...