Pastafarian
Pastafarian

Reputation: 2140

Transposing a SQL Server Table without aggregating

I have a SQL Server table which I'd like to transpose, i.e. switch the rows and columns.

The original table looks like this:

empname     empqual     emprank    empexp
Lily        MASTERS        1         9       
Sasha       UNIVERSITY     1         9
Harry       UNIVERSITY     1         9
Angela      MASTERS        4        10
Joyce       UNIVERSITY     5        11

Please note that the row data is dynamic and the above table is just to demonstrate the table schema.

EDIT: I'd like to modify the above table so that it looks like this:

DETAILS    Column1     Column2     Column3    Column4     Column5
empname     Lily       Sasha        Harry      Angela      Joyce
empqual    MASTERS    UNIVERSITY  UNIVERSITY  MASTERS    UNIVERSITY
emprank       1           1          1          4           5
empexp        9           9          9          10          11

I have looked through several online examples. The PIVOT function seems to be the most commonly-used function when tables are transposed, but since the operation I require doesn't involve any aggregations, unlike most other examples, I do not know how to do this. Apologies if this question is redundant and a possible answer already exists elsewhere.

Upvotes: 1

Views: 1418

Answers (2)

Giannis Paraskevopoulos
Giannis Paraskevopoulos

Reputation: 18411

You may check at this Fiddle

EDIT

I made it dynamic...

DECLARE @cols AS NVARCHAR(MAX),
    @query  AS NVARCHAR(MAX)

SET @cols = STUFF((SELECT distinct ',' + 'Column' + CONVERT(VARCHAR,Row_Number() OVER (Order By empname))
            FROM Table1 c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

SET @query = '
SELECT 1 as OrderBy,
       * 
FROM 
(
    SELECT ''Column'' + CONVERT(VARCHAR,Row_Number() OVER (Order By empname)) AS Columns, 
    CONVERT(VARCHAR,empname) as e, 
    ''empname'' AS Details
    FROM Table1 
) p
PIVOT
(
  MAX (e)
  FOR Columns IN
( 
  ' + @cols + ' )
) as pvt


UNION

SELECT 2 as OrderBy,
       * 
FROM 
(
    SELECT ''Column'' + CONVERT(VARCHAR,Row_Number() OVER (Order By empname)) AS Columns, 
    CONVERT(VARCHAR,empqual) as e, 
    ''empqual'' AS Details
    FROM Table1 
) p
PIVOT
(
  MAX (e)
  FOR Columns IN
( 
 ' + @cols + ' )
) as pvt

UNION

SELECT 3 as OrderBy,
       * 
FROM 
(
    SELECT ''Column'' + CONVERT(VARCHAR,Row_Number() OVER (Order By empname)) AS Columns, 
    CONVERT(VARCHAR,emprank) as e, 
    ''emprank'' AS Details
    FROM Table1 
) p
PIVOT
(
   MAX (e)
   FOR Columns IN
( 
  ' + @cols + ' )
) as pvt

UNION 

SELECT 4 as OrderBy,
       * 
FROM 
(
    SELECT ''Column'' + CONVERT(VARCHAR,Row_Number() OVER (Order By empname)) AS Columns, 
    CONVERT(VARCHAR,empexp) as e, 
    ''empexp'' AS Details
    FROM Table1 
) p
PIVOT
(
  MAX (e)
  FOR Columns IN
( 
  ' + @cols + ' )
) as pvt

order by OrderBy'

EXECUTE (@query)

Giannis

Upvotes: 1

Damien_The_Unbeliever
Damien_The_Unbeliever

Reputation: 239646

This query works for your sample data:

declare @t table(
    empname varchar(20) not null,
    empqual varchar(20) not null,
    emprank int not null,
    empexp int not null
)
insert into @t(empname,empqual,emprank,empexp) values
('Lily','MASTERS',1,9),    
('Sasha','UNIVERSITY',1,9),
('Harry','UNIVERSITY',1,9),
('Angela','MASTERS',4,10),
('Joyce','UNIVERSITY',5,11)

select *
from (select empname,empqual,CONVERT(varchar(20),emprank) as emprank,CONVERT(varchar(20),empexp) as empexp from @t) t
unpivot (value FOR measure in (empqual,emprank,empexp)) as unpvt
pivot (MAX(value) for empname in (Lily,Sasha,Harry,Angela,Joyce)) pvt
order by
    CASE measure WHEN 'empqual' THEN 0
                WHEN 'emprank' THEN 1
                WHEN 'empexp' THEN 2
                END

Result:

measure      Lily                 Sasha                Harry                Angela               Joyce
------------ -------------------- -------------------- -------------------- -------------------- --------------------
empqual      MASTERS              UNIVERSITY           UNIVERSITY           MASTERS              UNIVERSITY
emprank      1                    1                    1                    4                    5
empexp       9                    9                    9                    10                   11

If your comment about "row data is dynamic" means that you have an unknown list of names, then you'll need to write a query that obtains the list of names first, and then builds the above query using that list of names in the PIVOT section.

A simple search for "dynamic pivot" should find plenty of examples of doing so.

Upvotes: 0

Related Questions