Простой запрос SQL Pivot с неизвестным количеством столбцов - PullRequest
0 голосов
/ 13 июня 2019

У меня есть этот пример данных:

Item  Location
A   K
A   X
B   W
B   Z
B   Y
C   L

Я хотел бы получить такой результат:

Item    Loc1    Loc2    Loc3
A       K       X
B       W       Z       Y
C       L

Можно ли использовать оператор SQL Pivot?

Ответы [ 2 ]

0 голосов
/ 18 июня 2019

Вот один из способов использования синтаксиса сводного запроса с динамическим sql для генерации столбцов в требуемом формате.

Во-первых, я использую табличную переменную для хранения имен столбцов, это генерируется с помощью оконной функцииэто разделение на элементе, а затем упорядочивание на месте и объединение этого с 'Loc' для генерации Loc1, Loc2 и т. д.

Затем я передаю их в переменную, которая сформирует список столбцов.Это делается с помощью цикла while для последовательного добавления каждого нового столбца.

Оттуда я убираю список столбцов, чтобы удалить запятые.

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

create table #table (
    item char(1),
    location char(1)
);

insert #table (item, location)
values
('A',   'K'),
('A',   'X'),
('B',   'W'),
('B',   'Z'),
('B',   'Y'),
('C',   'L');

declare @pivotcols nvarchar(max)='';
declare @sql nvarchar(max)='';

declare @cols table (
colname nvarchar(150),
rowno int
);


insert @cols
select distinct '[Loc'+cast(rowno as nvarchar(10))+'],', rowno from
(
select row_number()over(partition by item order by location) as rowno,
       item, location 
from #table t)colgenerator;

while exists (select 1 from @cols)
    begin
    select top 1 @pivotcols = @pivotcols+colname from @cols order by rowno;
    delete from @cols where rowno in (select top 1 rowno from @cols order by rowno);
    end


select @pivotcols=substring(@pivotcols, 1, len(@pivotcols)-1);

select @sql=N'select item, '+@pivotcols+'
from (
select rowno, item, location from
(
select ''Loc''+cast(row_number()over(partition by item order by location) as nvarchar(1000)) as rowno,
       item, location 
from #table t)x)src
pivot (max(location) for rowno in ('+@pivotcols+')) piv;';


exec(@sql);

drop table #table;

enter image description here

0 голосов
/ 13 июня 2019

Я предпочитаю условную агрегацию:

select item,
       max(case when seqnum = 1 then location end) as location_1,
       max(case when seqnum = 2 then location end) as location_2,
       max(case when seqnum = 3 then location end) as location_3
from (select t.*, 
             row_number() over (partition by loc order by loc) as seqnum
      from t
     ) t
group by item;
...