Транспонирование и расширение столбчатого набора данных T-SQL - PullRequest
0 голосов
/ 25 декабря 2018

У меня есть таблица SQL, которая выглядит как следующий пример, который я создал в Excel: sample dataset


Ниже приведен желаемый результат.Мне нужно преобразовать данные выше в список из 2 столбцов:

Desired result


На случай, если понадобится больше информации, вот первая картинкаснова с примечаниями, описывающими, почему я использовал строки, которые у меня есть: input table + notes

Ответы [ 3 ]

0 голосов
/ 25 декабря 2018

UnPivot, безусловно, более производительный, но если вы хотите динамически разворачивать данные без фактического использования Dynamic SQL, рассмотрите следующий

Пример

Select A.fruiteater
      ,C.*
 From  fruits A
 Cross Apply ( values (cast((Select A.* for XML RAW) as xml))) B(XMLData)
 Cross Apply (
                Select Item  = a.value('local-name(.)','varchar(100)')
                      ,Value = a.value('.','varchar(max)') 
                 From  B.XMLData.nodes('/row')  as C1(n)
                 Cross Apply C1.n.nodes('./@*') as C2(a)
                 Where a.value('local-name(.)','varchar(100)') not in ('fruiteater','OtherColumnsToExclude')
             ) C

Возвращает

fruiteater  Item    Value
Aaron       Fruit1  Orange
Aaron       Fruit2  Pear
Aaron       Fruit3  Apple
Bob         Fruit1  Apple
Bob         Fruit2  Orange
Bob         Fruit3  Blueberries
Bob         Fruit4  Peach
Bob         Fruit5  Mango
Bob         Fruit6  Banana
Carter      Fruit1  Pear
Carter      Fruit2  Orange
Carter      Fruit3  Apple
David       Fruit1  Blueberries
Earnest     Fruit1  Mango
Earnest     Fruit2  Orange
Earnest     Fruit3  Pear
Earnest     Fruit4  Apple
Earnest     Fruit5  Blueberries
Frank       Fruit1  Raspberries
0 голосов
/ 25 декабря 2018

Я очень предпочитаю боковые соединения (apply) для этой цели.Я думаю, что синтаксис проще, и он не делает ничего «волшебного», например, удаляет NULL значения, если вы явно не хотите, чтобы он:

select f.fruiteater, v.fruit
from fruits f cross apply
     (values (fruit1),  (fruit2),  (fruit3), (fruit4), (fruit5), (fruit6)
     ) v(fruit)
where v.fruit is not null;

Что более важно, unpivot - это очень специфический синтаксис для одногоцель.Боковые соединения очень гибкие и мощные.Использование их для отмены - довольно простой способ узнать о них.

0 голосов
/ 25 декабря 2018

Вы можете использовать Unpivot, чтобы получить ожидаемые результаты.

create table fruits (fruiteater varchar(100), Fruit1 varchar(100), Fruit2 varchar(100), 
Fruit3 varchar(100), Fruit4 varchar(100), Fruit5 varchar(100), Fruit6 varchar(100))  

insert into fruits values ('Aaron', 'Orange', 'Pear', 'Apple', NULL, NULL, NULL) 
,('Bob', 'Apple', 'Orange', 'Blueberries', 'Peach', 'Mango', 'Banana') 
,('Carter', 'Pear', 'Orange', 'Apple', NULL, NULL, NULL) 
,('David', 'Blueberries', NULL, NULL, NULL, NULL, NULL) 
,('Earnest', 'Mango', 'Orange', 'Pear', 'Apple','Blueberries', NULL) 
,('Frank', 'Raspberries', NULL, NULL, NULL, NULL, NULL) 

Поскольку все эти фрукты будут в одном столбце, очень важно позаботиться о типе данных и длине при выполнении разворота, поэтому я убедился, что все столбцы имеют один и тот же тип данных.

select fruiteater, Value as Fruit from fruits
unpivot 
(value for columnname in ([Fruit1], [Fruit2], [Fruit3], [Fruit4], [Fruit5],[Fruit6]))unpvt 

Вывод: Unpivot позаботится о нулевых значениях, поскольку устраняет это.

fruiteater  Fruit
Aaron   Orange
Aaron   Pear
Aaron   Apple
Bob     Apple
Bob     Orange
Bob     Blueberries
Bob     Peach
Bob     Mango
Bob     Banana
Carter  Pear
Carter  Orange
Carter  Apple
David   Blueberries
Earnest Mango
Earnest Orange
Earnest Pear
Earnest Apple
Earnest Blueberries
Frank   Raspberries
...