How to represent rows as column from details table? [duplicate]
-
13-03-2021 - |
Pregunta
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:
Solución
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):
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