Skip to content
Advertisement

Join Two Tables Then Transpose Rows From One Table As Column Names

I’m trying to join two tables

ColumnNames
ID  |Name        |Type    |Status |
-----------------------------------------------------
1   |Fullname    |varchar |Active
2   |Email       |varchar |Active  
3   |Position    |varchar |Active  
4   |Category    |varchar |Active
ColumnValues
ID  |ColumnNameID |value                |Status |
-----------------------------------------------------
1   |1            |Linda                |Active
2   |2            |linda@email.com      |Active  
3   |3            |Soft Eng.            |Active  
4   |4            |Cat 1                |Active
5   |1            |Remil                |Active
6   |2            |Remil@email.com      |Active  
7   |3            |Senior Soft Eng.     |Active  
8   |4            |Cat 2                |Active   
9   |1            |Ash                  |Active
10  |2            |ash@email.com        |Active  
11  |3            |Soft Eng.            |Active  
12  |4            |Cat 1                |Active  

and then transposing rows of data (from Name on ColumnNames table) as column names.

Now, I was told to use Pivot. I’ve successfully used pivot for transposing rows from a single table, but I’m confused in how to transpose rows from joined tables.

Below is the code that I’ve tried, but it gives me an error saying columns doesn’t exist

    @query  AS NVARCHAR(MAX)

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(ColumnName) 
                    from tm.ColumnName
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT ColumnNameID, ' + @cols + ' from 
             (
                select i.ColumnNameID, i.ColumnValue
                from tm.ColumnValue i
                inner join tm.ColumnName a
                  on i.ColumnNameID = a.ColumnNameID
            ) x
            pivot 
            (
                max(ColumnNameID)
                for ColumnValue in (' + @cols + ')
            ) p '

execute(@query)

Expected Result Should be

Fullname  |Email                 |Position             |Category |
--------------------------------------------------------------------
Linda     |linda@email.com       |Soft Eng.            |Cat 1
Remil     |Remil@email.com       |Senior Soft Eng.     |Cat 2
Ash       |ash@email.com         |Soft Eng.            |Cat 1

Am I utilizing pivot correctly on this scenario?

Advertisement

Answer

Consider a ranking with ROW_NUMBER across each column value type (fullname, email, position, category) to be included in INNER JOIN then run through PIVOT. No need of dynamic building of SQL:

SELECT [Fullname], [Email], [Position], [Category]
FROM (
    SELECT i.ColumnValue, a.[Name],
           ROW_NUMBER() OVER (PARTITION BY a.[Name] ORDER BY a.ColumnNameID) AS rn
    FROM ColumnValues i
    INNER JOIN ColumnNames a
      ON i.ColumnNameID = a.ColumnNameID
  ) tbl

PIVOT
   (MAX(ColumnValue) 
    FOR [Name] IN ([Fullname], [Email], [Position], [Category])
   ) pvt
ORDER BY rn

Rextester demo

For a dynamic query, build a @cols string to place in specific places of pivot query.

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

SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[Name]) 
            FROM ColumnNames c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
             ,1,1,'')

SET @query = 'SELECT ' + @cols + '
                FROM (
                    SELECT i.ColumnValue, a.[Name],
                           ROW_NUMBER() OVER (PARTITION BY a.[Name] ORDER BY a.ColumnNameID) AS rn
                    FROM ColumnValues i
                    INNER JOIN ColumnNames a
                      ON i.ColumnNameID = a.ColumnNameID
                  ) tbl

                PIVOT
                   (MAX(ColumnValue) 
                    FOR [Name] IN (' + @cols + ')
                   ) pvt
                ORDER BY rn'

EXECUTE(@query)

Rextester demo

User contributions licensed under: CC BY-SA
5 People found this is helpful
Advertisement