TRANSFORM Avg(CASE WHEN [temp].[sumUnits] > 0
THEN [temp].[SumAvgRent] / [temp].[sumUnits]
ELSE 0
END) AS Expr1
SELECT [temp].[Description]
FROM [temp]
GROUP BY [temp].[Description]
PIVOT [temp].[Period];
Need to convert this query for sql server
I have read all other posts but unable to convert this into the same
Here is the equivalent version using the PIVOT table operator:
SELECT *
FROM
(
SELECT
CASE
WHEN sumUnits > 0
THEN SumAvgRent / sumUnits ELSE 0
END AS Expr1,
Description,
Period
FROM temp
) t
PIVOT
(
AVG(Expr1)
FOR Period IN(Period1, Period2, Period3)
) p;
SQL Fiddle Demo
For instance, this will give you:
| DESCRIPTION | PERIOD1 | PERIOD2 | PERIOD3 |
---------------------------------------------
| D1 | 10 | 0 | 20 |
| D2 | 100 | 1000 | 0 |
| D3 | 50 | 10 | 2 |
Note that When using the MS SQL Server PIVOT table operator, you have to enter the values for the pivoted column. However, IN MS Access, This was the work that TRANSFORM with PIVOT do, which is getting the values of the pivoted column dynamically. In this case you have to do this dynamically with the PIVOT operator, like so:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
SELECT #cols = STUFF((SELECT distinct
',' +
QUOTENAME(Period)
FROM temp
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET #query = ' SELECT Description, ' + #cols + '
FROM
(
SELECT
CASE
WHEN sumUnits > 0
THEN SumAvgRent / sumUnits ELSE 0
END AS Expr1,
Description,
Period
FROM temp
) t
PIVOT
(
AVG(Expr1)
FOR Period IN( ' + #cols + ')
) p ';
Execute(#query);
Updated SQL Fiddle Demo
This should give you the same result:
| DESCRIPTION | PERIOD1 | PERIOD2 | PERIOD3 |
---------------------------------------------
| D1 | 10 | 0 | 20 |
| D2 | 100 | 1000 | 0 |
| D3 | 50 | 10 | 2 |
I have a large file that has the following fields:
Table 1:
+---------+--------+-----------+
| User_Id | Key_Id | Value |
+---------+--------+-----------+
| 100 | 74 | 37 |
| 100 | 65 | Male |
| 100 | 279 | G235467 |
+---------+--------+-----------+
and I have another file that tells what each 'Key_Id' is called (they are column names) e.g.
Table 2:
+--------+------------------+
| Key_Id | Key |
+--------+------------------+
| 65 | Gender |
| 66 | Height |
| 74 | Age |
| 279 | ReferenceNo |
I want to create a table using the Key_Id names found in the Key column of table 2, transpose all of the values from table 1 into table 2, but also include the User_Id from table 1 as this relates to an individual.
PS. Table 2 has nearly 300 keys that would need turning into individual fields
So ultimately I would like a table that looks like this:
+---------+---------+--------+-------+--------------+--------+
| User_Id | Gender | Height | Age | ReferenceNo | etc |
+---------+---------+--------+-------+--------------+--------+
| 100 | Male | | 37 | G235467 | |
So that each User_Id is a row and that all the Keys are columns with their respective values
You can use a dynamic sql query as below.
Query
declare #sql as varchar(max);
select #sql = 'select t1.[User_Id], ' + stuff((select +
', max(case t2.[Key_Id] when ' + cast([Key_Id] as varchar(100)) +
' then t1.[Value] end) as [' + [Key] + '] '
from Table2
for xml path('')
), 1, 2, '') +
'from Table1 t1 left join Table2 t2 on t1.[Key_Id] = t2.[Key_Id] group by t1.[User_Id];'
exec(#sql);
Find a demo here
You need to get a coma-separated list of those 300 key names to be used in PIVOT/UNPIVOT operators in T-SQL like described here
https://learn.microsoft.com/en-us/sql/t-sql/queries/from-using-pivot-and-unpivot
you can use pivot as below:
Select * from (
Select u.UserId, k.[key], u.[Value] from table1 u
join table2 k on u.keyid = k.keyid ) a
pivot ( max([Value]) for [key] in ([Gender], [Height], [Age], [ReferenceNo]) ) p
For dynamic list of keys you can use dynamic sql as below:
Declare #cols1 varchar(max)
Declare #query nvarchar(max)
Select #cols1 = stuff((select ','+QuoteName([Key]) from table2 group by [Key] for xml path('')),1,1,'')
Set #Query = 'Select * from (
Select u.UserId, k.[key], u.[Value] from table1 u
join table2 k on u.keyid = k.keyid ) a
pivot ( max([Value]) for [key] in (' + #cols1 + ') ) p '
Select #Query --Check the generated query and execute by uncommenting below query
--exec sp_executesql #Query
I have a table like this:
time | sensor | value |
---------------------------
10:00:00 | 1 | 12.3 |
10:00:00 | 2 | 14.3 |
10:00:00 | 3 | 15.3 |
10:00:01 | 1 | 15.3 |
10:00:02 | 2 | 11.3 |
10:00:01 | 3 | 10.3 |
10:00:03 | 1 | 9.3 |
10:00:03 | 2 | 15.3 |
10:00:04 | 3 | 11.3 |
...
10:05:01 | 1 | 15.3 |
10:05:02 | 2 | 11.3 |
10:05:01 | 3 | 10.3 |
10:05:03 | 1 | 9.3 |
10:05:03 | 2 | 15.3 |
10:05:04 | 3 | 11.3 |
And I need a Pivot table where the measurements are averaged in time intervals of lets say one minute, and ordered by sensor:
time | sensor 1| sensor 2| sensor 3|
----------------------------------------
10:00:00 | 11 | 12 | 10 |
10:01:00 | 10 | 13 | 15 |
...
I learned how to do this in MySQL, but now I am forced to use SQL Server and apparently this is completely different to MySQL.
Any help is appreciated, also some non trivial tutorial on this would be helpful.
EDIT
Attempt after the reply from Giorgi Nakeuri:
DECLARE #cols VARCHAR(MAX)
SELECT STUFF((SELECT '],[' + CAST([Group] AS VARCHAR(10)) FROM tblGroups
GROUP BY [Group]
FOR XML PATH('')), 1, 2, '') + ']'
DECLARE #s VARCHAR(MAX) = 'with cte as(
SELECT tblData.Timestmp, tblSeries.GroupID as SensorID, tblData.SeriesID, tblData.DataValue
FROM tblData
INNER JOIN tblSeries ON tblData.SeriesID = tblSeries.SeriesID
WHERE (tblSeries.[SeriesName] = ' + 'ActivePower'
+ 'AND tblData.Timestmp > ' + '2015-02-05 00:00:00' + ' AND tblData.Timestmp < ' + '2015-02-05 23:59:59'
+ 'AND tblData.DataValue>100)
)
select * from cte
pivot(AVG(DataValue) for GroupID in(' + #cols + ' )) p'
EXEC(#s)
The result is:
[150],[151],[152],[154],[159],[160],[164],[165],[166],[167],[168],[169],[171],[172],[173],[174],[175],[176],[180],[181],[182],[184],[185],[186],[187],[188],[189],[191],[192],[193],[194],[195],[196],[197],[20],[201],[205],[206],[207],[208],[209],[21],[210],[217],[218],[219],[220],[221],[222],[223],[224],[225],[226],[227],[228],[229],[231],[232],[233],[236],[237],[249],[251],[252],[253],[254],[258],[259],[260],[262],[263],[276],[277],[278],[279],[281],[288],[289],[290],[291],[293],[294],[295],[296],[300],[301],[302],[304],[308],[309],[314],[315],[316],[317],[324],[326],[329],[330],[331],[332],[333],[334],[335],[339],[340],[344],[347],[348],[351],[352],[353],[354],[355],[356],[357],[359],[370],[372],[373],[374],[375],[376],[380],[381],[382],[383],[384],[385],[386],[387],[388],[389],[390],[394],[395],[396],[397],[398],[400],[404],[405],[406],[407],[408],[409],[410],[411],[412],[413],[414],[418],[419],[420],[421],[425],[432],[435],[436],[437],[438],[439],[443],[444],[445],[452],[453],[457],[465],[466],[467],[468],[484],[485],[486],[487],[494],[495],[498],[499],[501],[506],[507],[511],[515],[516],[520],[521],[523],[527],[530],[531],[532],[533],[548],[550],[601],[605],[614],[615],[617],[81],[82],[829]
This are the sensor ID's, but not the Pivot table...
Try this:
select * from someTable
pivot(AVG(value) for sensor in([1],[2],[3])) p
If you have more columns in your table that you have showed then:
with cte as(select time, sensor, value from someTable)
select * from cte
pivot(AVG(value) for sensor in([1],[2],[3])) p
Dynamic version:
DECLARE #cols VARCHAR(MAX) = ''
SELECT #cols = STUFF((SELECT '],[' + CAST([Group] AS VARCHAR(10)) FROM tblGroups
WHERE [Group] <> 'meteo'
GROUP BY [Group]
FOR XML PATH('')), 1, 2, '') + ']'
DECLARE #s VARCHAR(MAX) = 'with cte as(
SELECT DATEADD(mi, datediff(mi, 0, tblData.Timestmp), 0) Timestmp, tblSeries.GroupID as SensorID, tblData.DataValue
FROM tblData INNER JOIN tblSeries ON tblData.SeriesID = tblSeries.SeriesID
WHERE tblSeries.[SeriesName] = ' + '''ActivePower''' + ' AND tblData.Timestmp > ''' + '2015-02-05 00:00:00''' + '
AND tblData.Timestmp < ' + '''2015-02-05 23:59:59''' + ' AND tblData.DataValue>100
)
select * from cte
pivot(AVG(DataValue) for GroupID in(' + #cols + ' )) p'
EXEC( #s)
I have a table with four columns item_id, color, size, weight, I want to show my table rows into one row like item1,color1,size1,weight1,item2,color2,...........,item4,color4,size4,weight4 ...
Following is my table
+---------+--------+--------+--------+
| item_id | color | size | weight |
+---------+--------+--------+--------+
| 1 | blue | large | 65 |
| 2 | orange | large | 57 |
| 3 | red | small | 12 |
| 4 | violet | medium | 34 |
My desired result will be
+---------+--------+--------+--------++---------+--------+--------+
| item_id1| color1| size1 | weight1| item_id2 | color2 | size2 | weight2 |....
+---------+--------+--------+--------+---------+--------+--------+---------------
| 1 | blue | large| 65 | 2 | orange | large | 57 |...
+---------+--------+--------+--------+ +---------+--------+--------+--------+
Thanks in advance.
In order to get this result, you will need to do a few things:
UNPIVOT the current data
PIVOT the result from the unpivot
use dynamic SQL since you will have an unknown number of rows
Since you are using SQL Server 2005+ you can use CROSS APPLY to unpivot the data, this process takes your multiple columns of item_id, color, size and weight and converts them into multiple rows:
select col+'_'+cast(seq as varchar(50)) col,
value
from
(
select item_id as seq, item_id, color, size, weight
from yourtable
) d
cross apply
(
values
('item_id', cast(item_id as varchar(50))),
('color', color),
('size', size),
('weight', cast(weight as varchar(50)))
) c (col, value);
See SQL Fiddle with Demo. This gives a result:
| COL | VALUE |
----------------------
| item_id_1 | 1 |
| color_1 | blue |
| size_1 | large |
| weight_1 | 65 |
| item_id_2 | 2 |
| color_2 | orange |
| size_2 | large |
| weight_2 | 57 |
| item_id_3 | 3 |
As you can see from the result you now have multiple rows in based off your original data. The COL values are the values that you will use to PIVOT. The full dynamic SQL code will be similar to the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(col+'_'+cast(item_id as varchar(10)))
from yourtable
cross apply
(
select 'item_id', 0 union all
select 'color', 1 union all
select 'size', 2 union all
select 'weight', 3
) c (col, so)
group by item_id, col, so
order by item_id, so
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT ' + #cols + '
from
(
select col+''_''+cast(seq as varchar(50)) col,
value
from
(
select item_id as seq, item_id, color, size, weight
from yourtable
) d
cross apply
(
values
(''item_id'', cast(item_id as varchar(50))),
(''color'', color),
(''size'', size),
(''weight'', cast(weight as varchar(50)))
) c (col, value)
) x
pivot
(
max(value)
for col in (' + #cols + ')
) p '
execute(#query);
See SQL Fiddle with Demo. The final result is:
| ITEM_ID_1 | COLOR_1 | SIZE_1 | WEIGHT_1 | ITEM_ID_2 | COLOR_2 | SIZE_2 | WEIGHT_2 | ITEM_ID_3 | COLOR_3 | SIZE_3 | WEIGHT_3 | ITEM_ID_4 | COLOR_4 | SIZE_4 | WEIGHT_4 |
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------
| 1 | blue | large | 65 | 2 | orange | large | 57 | 3 | red | small | 12 | 4 | violet | medium | 34 |
If you want to do it programmatically and you don't know the number of rows try this :
DECLARE #I INT, #END INT, #DATA nvarchar(max), #TEMPSTR nvarchar(max), #DynamicTableSQL nvarchar(max)
SET #I = 1
SET #DATA = ''
SET #TEMPSTR = ''
SELECT #END = MAX(item_id) from items
SET #DynamicTableSQL = 'DECLARE #DynamicTable TABLE('
WHILE #I <= #END
BEGIN
--SELECT #I
SET #TEMPSTR = (select CAST(item_id as nvarchar) + ',''' + color + ''',''' + size + ''',' + cast(weight as nvarchar) + ',' FROM items WHERE item_id = #I)
SET #DynamicTableSQL = #DynamicTableSQL + 'item_id_' + CAST(#I AS VARCHAR(10))+ ' INT ,' + 'color_' + CAST(#I AS VARCHAR(10))+ ' NVARCHAR(15) ,'+ 'size_' + CAST(#I AS VARCHAR(10))+ ' NVARCHAR(15) ,'+ 'weight_' + CAST(#I AS VARCHAR(10))+ ' INT ,'
SET #DATA += #TEMPSTR
SELECT #I = #I + 1
END
SET #DynamicTableSQL = SUBSTRING(#DynamicTableSQL, 0, LEN(#DynamicTableSQL))
SET #DynamicTableSQL = #DynamicTableSQL + ') '
SET #DATA = SUBSTRING(#DATA, 0, LEN(#DATA))
SET #DynamicTableSQL = #DynamicTableSQL + ' INSERT INTO #DynamicTable VALUES (' + #DATA + ')'
SET #DynamicTableSQL = #DynamicTableSQL + ' SELECT * FROM #DynamicTable '
EXEC SP_EXECUTESQL #DynamicTableSQL