2015-07-13 3 views
3

Я пытаюсь сделать PIVOT на столе с двумя рядами, как это:SQL Pivot с помощью всего двух столбцов

Category  | Sector 
--------------------------- 
Bulbs   | DIY 
Bulbs   | Home 
Picnic blanket | DIY 
Picnic blanket | Home 
Picnic blanket | Interior 

Каждая категория может иметь 1 или несколько секторов.

Я пытаюсь получить таблицу, как это:

Category  | Sector 1 | Sector 2 | Sector 3 
------------------------------------------------- 
Bulbs   | DIY  | Home  | NULL 
Picnic blanket | DIY  | Home  | Interior 

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

SELECT 
    dbo.fn_DbContent_GetTranslation(pt.Name_DbContentId, 2) 'Category' 
    , dbo.fn_DbContent_GetTranslation(s.Name_DbContentId, 2) 'Sector' 
FROM dbo.ProductType pt 
JOIN dbo.ProductTypeMandator ptm ON ptm.ProductTypeId = pt.Id 
JOIN dbo.ProductTypeMandator2PortalSector ptmps ON ptmps.ProductTypeMandatorId = ptm.Id 
JOIN dbo.PortalSector ps ON ps.Id = ptmps.PortalSectorId 
JOIN dbo.Sector s ON s.Id = ps.SectorId 
WHERE 
    ptmps.PortalSectorId IN (21, 18, 19) 

я уже сделал PIVOT, но с таблицей, содержащей три колонки, где содержащаяся один значения для заголовков в сводной таблице. В этом случае значения для заголовка отсутствуют, поэтому я не знаю, как это сделать.

Спасибо за помощь

+2

Есть ли ограничение на количество секторов и/или номер, который вы хотите отобразить? Любой отдельный запрос имеет фиксированную «форму» (количество столбцов, их имена и типы данных), поэтому, если вам нужно поддерживать неограниченное число, вы ищете динамический SQL для построения запроса. –

+0

Как вы получили этот заказ 'сектор 1, сектор 2..' –

ответ

2

Вы можете решить, что путь:

-- Create demo data 
CREATE TABLE #cats(category nvarchar(25), sector nvarchar(25)) 

INSERT INTO #cats(category, sector) 
VALUES (N'Bulbs',N'DIY'), 
     (N'Bulbs',N'Home'), 
     (N'Picnic blanket',N'DIY'), 
     (N'Picnic blanket',N'Home'), 
     (N'Picnic blanket',N'Interior') 

SELECT * 
FROM (
    SELECT category, sector 
    FROM #cats 
) as dat 
PIVOT(
    MAX(sector) 
    FOR sector IN([DIY],[Home],[Interior]) 
) as pvt 

-- Cleanup 
DROP TABLE #cats 

Если вы хотите, чтобы это назвать правильно, так как в вашем примере, вы можете объединить его с именем нумерацией:

-- Create demo data 
CREATE TABLE #cats(category nvarchar(25), sector nvarchar(25)) 

INSERT INTO #cats(category, sector) 
VALUES (N'Bulbs',N'DIY'), 
     (N'Bulbs',N'Home'), 
     (N'Picnic blanket',N'DIY'), 
     (N'Picnic blanket',N'Home'), 
     (N'Picnic blanket',N'Interior') 

SELECT * 
FROM (
    SELECT category, sector, N'Sector '+CONVERT(nvarchar(max),DENSE_RANK() OVER(ORDER BY sector)) as rn 
    FROM #cats 
) as dat 
PIVOT(
    MAX(sector) 
    FOR rn IN([Sector 1],[Sector 2],[Sector 3]) 
) as pvt 

-- Cleanup 
DROP TABLE #cats 

И последнее, но не менее, если вы хотите быть динамичным:

-- Create demo data 
CREATE TABLE #cats(category nvarchar(25), sector nvarchar(25)) 

INSERT INTO #cats(category, sector) 
VALUES (N'Bulbs',N'DIY'), 
     (N'Bulbs',N'Home'), 
     (N'Picnic blanket',N'DIY'), 
     (N'Picnic blanket',N'Home'), 
     (N'Picnic blanket',N'Interior') 

DECLARE @sql nvarchar(max), @cols nvarchar(max) 

-- get proper column list 
SELECT @cols = COALESCE(@cols + N',[' + grCols.rn + N']',N'[' + grCols.rn + N']') 
FROM (
    SELECT DISTINCT N'Sector '+CONVERT(nvarchar(max),DENSE_RANK() OVER(ORDER BY sector)) as rn 
    FROM #cats 
) as grCols 

SET @sql = N' 
SELECT * 
FROM (
    SELECT category, sector, N''Sector ''+CONVERT(nvarchar(max),DENSE_RANK() OVER(ORDER BY sector)) as rn 
    FROM #cats 
) as dat 
PIVOT(
    MAX(sector) 
    FOR rn IN('[email protected]+') 
) as pvt' 
EXEC(@sql) 

-- Cleanup 
DROP TABLE #cats 
+0

полностью сработал для меня спасибо! – sandrowi

+0

Приятно вам помочь. – Ionic

0

Вы можете сделать это двумя способами,

Один Conditional Aggregate

;WITH cte 
    AS (SELECT *, 
       rn=Row_number() 
        OVER(
         partition BY category 
         ORDER BY (SELECT NULL)) 
     FROM yourtable) 
SELECT category, 
     [sector 1] = Max(CASE WHEN rn = 1 THEN sector END), 
     [sector 2] = Max(CASE WHEN rn = 2 THEN sector END), 
     [sector 3] = Max(CASE WHEN rn = 3 THEN sector END) 
FROM cte 
GROUP BY category 

Другой способ использует Pivot

SELECT * 
FROM (SELECT *, 
       sector_col = 'sector ' 
          + Cast(Row_number()OVER(partition BY category ORDER BY (SELECT NULL)) AS VARCHAR(20)) 
     FROM yourtable) A 
     PIVOT (Max(sector) 
      FOR sector_col IN ([sector 1], 
           [sector 2], 
           [sector 3])) piv 

Примечание: Как уже упоминалось в комментариях, если sector значений не являются static или unknown, то у вас может быть конвертация их в dynamic query

Смежные вопросы