To convert rows into columns, you need to use Pivot
in Sql Server
. If you know the number of columns in advance, you can use pivoting statically as the answer suggested by Gordin Linoff.
Sometimes, the number of colors
may vary(in your example there are only 3 colors). In such case, you cannot hardcode the column names. For that first of all you need to get columns names dynamically into a variable.
DECLARE @cols NVARCHAR (MAX)
SELECT @cols = COALESCE (@cols + ',[' + COLUMNNAME + ']', '[' + COLUMNNAME + ']')
FROM
(
SELECT DISTINCT
'COLOR'+CAST(ROW_NUMBER() OVER(PARTITION BY INVOICE,PRODUCT ORDER BY (SELECT 0)) AS VARCHAR(10)) COLUMNNAME
FROM #TEMP
) PV
ORDER BY COLUMNNAME
Now the above variable have values of columns as Comma Separated Values
which can be used with IN
operator dynamically for the below query. Since your table doesn't have values like COLOR1
, COLOR2
etc, I have provided logic to get column names for each INVOICE
and its PRODUCT
using PARTITION BY clause.
DECLARE @query NVARCHAR(MAX)
SET @query = '-- This outer query forms your pivoted result
SELECT * FROM
(
-- Source data for pivoting
SELECT DISTINCT INVOICE,PRODUCT,COLOR,
''COLOR''+CAST(ROW_NUMBER() OVER(PARTITION BY INVOICE,PRODUCT ORDER BY (SELECT 0)) AS VARCHAR(10)) COLUMNNAME
FROM #TEMP
) x
PIVOT
(
--Defines the values in each dynamic columns
MIN(COLOR)
-- Get the names from the @cols variable to show as column
FOR COLUMNNAME IN (' + @cols + ')
) p
ORDER BY INVOICE;'
EXEC SP_EXECUTESQL @query