Dynamic PIVOT ваш друг:
LiveDEMO
CREATE TABLE #mytable(
Name VARCHAR(80) NOT NULL
,Product VARCHAR(160) NOT NULL
);
INSERT INTO #mytable VALUES ('Mayer','Product_1');
INSERT INTO #mytable VALUES ('Mayer','Product_1');
INSERT INTO #mytable VALUES ('Mayer','Product_2');
INSERT INTO #mytable VALUES ('Kowalsky','Product_1');
INSERT INTO #mytable VALUES ('Kowalsky','Product_2');
INSERT INTO #mytable VALUES ('Kowalsky','Product_3');
INSERT INTO #mytable VALUES ('Kowalsky','Product_4');
DECLARE @cols NVARCHAR(MAX),
@cols_piv NVARCHAR(MAX),
@query NVARCHAR(MAX)
,@max INT = 0;
SELECT @max = MAX(c)
FROM (
SELECT Name, COUNT(Product) AS c
FROM #mytable
GROUP BY Name) AS s;
SET @cols = STUFF(
(SELECT ',' + CONCAT('[',c.n, '] AS Purchase_',c.n, ' ')
FROM (SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects ORDER BY n)AS c(n)
WHERE c.n <= @max
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @cols_piv = STUFF(
(SELECT ',' + CONCAT('[',c.n, '] ')
FROM (SELECT TOP (1000) n = ROW_NUMBER() OVER (ORDER BY [object_id]) FROM sys.all_objects ORDER BY n)AS c(n)
WHERE c.n <= @max
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET @query = N'SELECT Name, ' + @cols + ' from
(
select Name, Product,
[rn] = ROW_NUMBER() OVER (PARTITION BY Name ORDER BY Product)
from #mytable
) x
pivot
(
max(Product)
for rn in (' + @cols_piv + ')
) p ';
-- SELECT @query;
EXEC [dbo].[sp_executesql]
@query;
Это может быть сложным на первый, но это действительно просто. Нормальный PIVOT
требует, чтобы вы знали список столбцов заранее. Это не вариант в вашем случае, поэтому вам нужно создать столбец и использовать Dynamic-SQL.
Как это работает:
@max
содержит максимальное количество столбцов в строке
@cols
содержит SELECT
список столбцов с псевдонимами
@cols_piv
содержит список номеров [1], [2], ... @max
- сцепить его с нормальным
PIVOT
запроса
- Выполните его и получите удовольствие от ваших результатов.
Предупреждение:
Я использовал sys.objects
как мой генератор чисел. Вы можете заменить его тем, что хотите (рекурсивная CTE/многоступенчатая CTE/таблица таблеток ...).
Если вы используете SQL Server 2008, вам необходимо заменить CONCAT
на +
.
- это имя и продукт только 2 столбца в исходной таблице? – JamieD77
@ JamieD77 Да, только эти два. :) – JimBoy
, тогда преобразование их в столбцы не имеет смысла, потому что нет определенного порядка. – JamieD77