Reputation: 49
I currently have a table in SQL Server that looks something like this:
Machine | Serial | Date | Parameter | Value |
---|---|---|---|---|
Machine 1 | 12345 | 7/22/2021 | Param 1 | 789 |
Machine 1 | 12345 | 7/22/2021 | Param 2 | 456 |
Machine 1 | 67890 | 7/22/2021 | Param 1 | 123 |
Machine 1 | 67890 | 7/22/2021 | Param 2 | 456 |
Machine 1 | 34567 | 7/22/2021 | Param 1 | 789 |
Machine 1 | 34567 | 7/22/2021 | Param 3 | 123 |
I am attempting to create a view that transforms this table into something like this, where each row is defined by it's serial number and the view headers are defined dynamically by the parameters in the 'Parameter' column
Serial | Machine | Date | Param 1 | Param 2 | Param 3 |
---|---|---|---|---|---|
12345 | Machine 1 | 7/22/2021 | 789 | 456 | |
67890 | Machine 1 | 7/22/2021 | 123 | 456 | |
34567 | Machine 1 | 7/22/2021 | 789 | 123 |
The intention here is that the original table can contain any number of unique parameters and the resultant view will then group by serial number and populate each column with it's respective value based on the parameter it is assigned.
So far I've tried messing with dynamic SQL but have not been able to produce any results. I have done similar things in the past without a dynamic number of parameters in the parameter column. Is something like this even possible on the database side or does this kind of manipulation need to happen on the client side?
Upvotes: 0
Views: 2464
Reputation: 82020
If you want to perform this in SQL Server and not the presentation layer, Dynamic SQL would be required
Example
Declare @SQL varchar(max) = '
Select *
From (
Select Serial
,Machine
,Date
,Parameter
,Value
From #YourTable
) src
Pivot (sum(Value) For [Parameter] in (' + stuff((Select Distinct ',' + QuoteName(Parameter) From #YourTable Order By 1 For XML Path('') ),1,1,'') + ') ) pvt'
Exec(@SQL);
Results
Upvotes: 2
Reputation: 725
One approach would be to use CASE statements on additional columns in your view definition like this:
SELECT Serial,
Machine,
Date,
CASE WHEN Parameter = 'Param1' THEN Value ELSE '' END AS Param1,
CASE WHEN Parameter = 'Param2' THEN Value ELSE '' END AS Param2,
CASE WHEN Parameter = 'Param3' THEN Value ELSE '' END AS Param3
This won't scale well to a large number of parameters, but it should work fine for what you've described here.
If you need this to be dynamic or to accommodate more values you should look into using a PIVOT
Edit: Adding that approach as well, for completeness.
DROP TABLE IF EXISTS #pivot;
CREATE TABLE #pivot
(Serial INT,
Machine VARCHAR(20),
[Date] DATETIME,
Parameter VARCHAR(6),
VALUE INT)
INSERT INTO #pivot
VALUES (12345, 'Machine 1', GETDATE(), 'Param1', 789),
(12345, 'Machine 1', GETDATE(), 'Param2', 456),
(67890, 'Machine 1', GETDATE(), 'Param1', 789),
(67890, 'Machine 1', GETDATE(), 'Param2', 456),
(34567, 'Machine 1', GETDATE(), 'Param1', 789),
(34567, 'Machine 1', GETDATE(), 'Param3', 123);
SELECT *
FROM #pivot;
SELECT Serial, Machine, Date, Param1, Param2, Param3
FROM #pivot AS p
PIVOT (
SUM(p.Value)
FOR p.Parameter
IN (Param1, Param2, Param3)
) pvt
Upvotes: 0