Reputation: 13
I have a table stored in a SQL Server database that contains user ID, Product Name and values by week stored in columns. The column names for the weeks are named like this "trx_2015#08#07" and the value for that week is stored in each column:
UserId, ProductName, trx_2015#08#07, trx_2015#08#014, trx_2015#08#21
I would like to clean up those column names (I can't alter the table) to just be the week value (2015-08-07) then pivot the data to be in this format:
userID, ProductName, Week, Value
Any thoughts on the easiest way to accomplish this?
Upvotes: 1
Views: 202
Reputation: 670
SQL Server provides a method for manipulating the data as you would like to with the use of the UNPIVOT
relational operator. Below is an example of how to accomplish this in addition to dynamically obtaining the column names (ideally, we would not want to update the query every time a column is added).
CREATE TABLE tbl (
UserId INT,
ProductName NVARCHAR(1000),
[trx_2015#08#07] INT,
[trx_2015#08#014] INT,
[trx_2015#08#21] INT
);
INSERT INTO tbl(UserId, ProductName, [trx_2015#08#07], [trx_2015#08#014], [trx_2015#08#21])
VALUES (1, 'Product #1', 123, 456, 789);
trx
column namesWe will need an aggregate concatenation of the trx
colmn names to pass to the UNPIVOT
relational overator's IN
clause.
SELECT STUFF((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'tbl'
AND COLUMN_NAME LIKE 'trx_%'
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')
Ultimately, we would like the query to look like this:
SELECT UserId, ProductName, Value, trx
FROM tbl
UNPIVOT(
Value FOR trx IN ([trx_2015#08#014],[trx_2015#08#07],[trx_2015#08#21])
) AS unpvt
The query must be built dynamically in SQL because the IN
clause here cannot accept a result set.
Query:
DECLARE @SQLString NVARCHAR(MAX);
SET @SQLString = CONCAT(
'SELECT UserId, ProductName, Value, trx FROM tbl UNPIVOT(Value FOR trx IN (',
(SELECT STUFF((SELECT ',' + QUOTENAME(COLUMN_NAME)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE
TABLE_NAME = 'tbl'
AND COLUMN_NAME LIKE 'trx_%'
FOR XML PATH(''), TYPE).value('.', 'nvarchar(max)'), 1, 1, '')),
')) AS unpvt'
);
EXEC(@SQLString);
Result Set:
UserId ProductName Value trx
1 Product #1 456 trx_2015#08#014
1 Product #1 123 trx_2015#08#07
1 Product #1 789 trx_2015#08#21
Upvotes: 1