sandrowi
sandrowi

Reputation: 113

SQL Pivot with just two Columns

I'm trying to do a PIVOT on a table with two rows like this:

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

Each category can have 1 or more sectors.

I'm trying to get a table like this:

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

The query looks like this:

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)

I already did a PIVOT but with a table containing three columns where one contained the values for the headers in the pivot table. In this case the values for the header are missing so I don't know how to do it then.

Thanks for helping

Upvotes: 4

Views: 110

Answers (2)

Pரதீப்
Pரதீப்

Reputation: 93694

You can do this in two ways,

One is 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

Another way is using 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 

Note : As mentioned in comments if the sector values are not static or unknown then you may have convert the same to dynamic query

Upvotes: 0

Ionic
Ionic

Reputation: 3935

You can solve it that way:

-- 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

If you want it to be named correctly as in your example, you can combine it with a named numbering:

-- 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

And last but not least, if you want it to be dynamical:

-- 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('+@cols+')
) as pvt'
EXEC(@sql)

-- Cleanup
DROP TABLE #cats

Upvotes: 2

Related Questions