Question

I work on SQL Server 2012 and I have an issue: I can't represent rows as columns.

I need to represent code type from details table to display as column with values of count parts from details table, join between master and details by plid. Every plid have a group of code type so instead of represent code type as rows, I will represent it as columns. Columns will have header as code type and content column will be count parts.

How to do that?

create table #master
 (
 zplid int,
 zplidname  nvarchar(50)
 )
 insert into #master(zplid,zplidname) 
 values
 (4124,'tetanium'),
 (4125,'FilmCapacitor'),
 (4145,'CeramicCapacitor'),
 (4170,'Holetransistor'),
 (4190,'resistor')

 create table #details
 (
 zplid int,
 CodeType  int,
 CountParts int
 )
 insert into #details(zplid,CodeType,CountParts) 
 values
 (4124,9089,9011),
 (4124,7498,7000),
 (4125,9089,2000),
 (4125,7498,1000),
 (4145,9089,3000),
 (4145,7498,8500),
 (4170,9089,7600),
 (4170,7498,6600),
 (4190,9089,9001),
 (4190,7498,9003)

Result:

join between master and details

Was it helpful?

Solution

You'll want to use the PIVOT operator in SQL Server. (Note UNPIVOT is really useful to know as well).

This StackOverflow Answer gives a really good walkthrough on how to utilize PIVOT.

You basically want a query like this:

WITH CTE_MasterDetails AS -- Join your Master and Details together first in a CTE
(
    SELECT M.zplid, M.zplidname, D.CodeType, D.CountParts
    FROM #master AS M
    LEFT JOIN #details AS D -- Left joining just in case not all Master records have a corresponding Details record
        ON M.zplid = D.zplid
)

-- Final select from the CTE above, using a PIVOT to transpose the rows as columns
SELECT *
FROM 
(
    SELECT zplid, zplidname, CountParts, CodeType
    FROM CTE_MasterDetails
) SRC -- This is the source of the following Pivot operation
PIVOT
(
    MAX(CountParts) -- Value field
    FOR CodeType IN ([9089], [7498]) -- Pivoted Column Headers (on CodeType column's values)
) PIV
ORDER BY zplid;

The above example outputs the following results (using your sample scripts to build the #Master and #Details tables):

Results


Here's an example query with the same output as above but using dynamic SQL to dynamically generate the columns on CodeType:

DECLARE @Cols AS NVARCHAR(MAX), -- To hold the dynamically generated column list string
        @Query AS NVARCHAR(MAX) -- To hold the dynamic SQL of the Pivot query

-- Dynamically generate the column list string
SELECT @Cols = 
    STUFF
    (
        (
            SELECT ',[' + CAST(CodeType AS NVARCHAR(MAX)) + ']'
            FROM #Details
            GROUP BY CodeType
            ORDER BY CodeType DESC
            FOR XML PATH('')
        ),
        1,
        1,
        ''
    )

-- Dynamic SQL of the Pivot query
SET @Query =
'
WITH CTE_MasterDetails AS
(
    SELECT M.zplid, M.zplidname, D.CodeType, D.CountParts
    FROM #master AS M
    LEFT JOIN #details AS D
        ON M.zplid = D.zplid
)

SELECT *
FROM 
(
  SELECT zplid, zplidname, CountParts, CodeType
  FROM CTE_MasterDetails
) SRC
PIVOT
(
  MAX(CountParts)
  FOR CodeType IN (' + @Cols + ')
) PIV
ORDER BY zplid;
'

-- Executing the dynamic SQL generated above
EXEC sp_ExecuteSQL @Query
Licensed under: CC-BY-SA with attribution
Not affiliated with dba.stackexchange
scroll top