I am working on a aggregate report and I have got so far with the data but I am unsure how to proceed from here. I get by with SQL but my skills are limited
I have the follow in a temp table
ID Count Action
2 23 Installed
2 12 Uninstalled
2 36 Unchanged
3 12 Installed
3 25 Unchanged
4 35 Installed
4 25 Unchanged
I want to convert this into this format
ID Installed Uninstalled Unchanged
2 23 12 36
3 12 0 36
4 35 0 25
I have no idea where to go or even how to start to achieve this and cannot find anything to point me in the right direction (Im sure its there somewhere)
Any help would be appriciated
Try this:
SELECT
ID,
MAX(CASE WHEN "Action" = 'Installed' THEN Count END) AS 'Installed',
MAX(CASE WHEN "Action" = 'Uninstalled ' THEN Count END) AS 'Uninstalled',
MAX(CASE WHEN "Action" = 'Unchanged' THEN Count END) AS 'Unchanged'
FROM Table
GROUP BY ID;
Or using the SQL Server PIVOT table operator like so:
SELECT *
FROM
(
SELECT * FROM table
)t
PIVOT
(
MAX("Count") FOR "Action" IN([Installed], [Uninstalled], [Unchanged])
) p
SQL Fiddle Demo for both
However, for unknown number of Actions, you will have to select them dynamically like so:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Action)
from Table1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
SET #query = 'SELECT ID, ' + #cols + ' from
(
SELECT * FROM Table1
) x
PIVOT
(
MAX(count)
FOR action IN (' + #cols + ')
) p ';
EXECUTE(#query);
SQL Fiddle Demo(Dynamic Version)
It's called a pivot
Here's the documentation about it
The syntax is
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
Pivots are good, but very slow at times. Try it without one.
SELECT ID
, SUM(CASE WHEN [Action] = 'Installed' THEN [Count] ELSE 0 END) AS Installed
, SUM(CASE WHEN [Action] = 'Uninstalled' THEN [Count] ELSE 0 END) AS Uninstalled
, SUM(CASE WHEN [Action] = 'Unchanged' THEN [Count] ELSE 0 END) AS Unchanged
FROM <table>
GROUP BY ID
Related
I'm trying to create a dynamic pivot table in SQL that will report based on month and year. I did a bunch of research and was able to come up with the below query:
declare #dynamic nvarchar(max),
#column nvarchar(max);
set #column = N'';
select #column += N'' + datename(month,incurdate) +' '+ datename(year,incurdate) + ','
from (select distinct a.incurdate from artable a) as Transpose
select #column = substring(#column,0,len(#column))
set #dynamic = 'select * from
(
select month, incurdate, dolamount
from artable join dolentry on month = period
) b
pivot(sum(dolamount) for incurdate in (' + #column + ')) as PivotTable'
execute sp_executesql #dynamic
I am able to print the #column variable successfully, but the problems happen when I try to set it in the #dynamic variable. The error message is 'Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '1990'.' 1990 is the first year of the first pivoted column. Any help or tips are appreciated. Thanks!
You need to use QUOTENAME in the following code:
select #column += N'' + QUOTENAME(datename(month,incurdate) +' '+ datename(year,incurdate)) + ','
from (select distinct a.incurdate from artable a) as Transpose
in order to get output like this:
[col01], [col02], [col03], ... , [col04]
As you can see from the docs, the PIVOT syntax requires the pivoting columns to be wrapped in square brackets:
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
I have a table with 2 columns TimeStamp and ID in MS SQLSERVER
TimeStamp ID
2015-05-20 1
2015-05-20 2
2015-05-20 1
2015-05-21 1
2015-05-21 2
2015-05-21 2
2015-05-21 1
My requirement is to calculate number of records for every Id according to date.
Requirement:
Date No of records for Id=1 No. records for ID=2 Total
2015-05-20 2 1 3
2015-05-21 2 2 4
Please let me know how can i do this for other columns as well.
Thanks
Using Pivot - can look like this:
SELECT [TimeStamp], [1] AS [No of records for Id=1], [2] AS [No of records for Id=2], [1]+[2] AS Total
FROM dbo.YourTable
PIVOT
(
COUNT(ID) FOR ID IN ([1],[2])
) pvt
ORDER BY [TimeStamp]
For completion the Dynamic Way:
DECLARE #id_values NVARCHAR(MAX)
DECLARE #stmt NVARCHAR(MAX)
SET #id_values = ''
SET #stmt = ''
--Get List of ID's
SELECT #id_values = #id_values + ',[' + CAST(ID AS VARCHAR) + ']'
FROM dbo.YourTable
GROUP BY ID
SET #id_values = RIGHT(#id_values, LEN(#id_values)-1) --Remove Leading Comma
--Build PIVOT Statement
SET #stmt = 'SELECT [TimeStamp],' + #id_values + ','+ REPLACE(#id_values,',','+') + ' AS Total
FROM dbo.YourTable
PIVOT
(
COUNT(ID) FOR ID IN (' + #id_values + ')
) pvt
ORDER BY [TimeStamp]'
--Execute
EXEC sp_executesql #stmt
I've got your answer using subqueries:
SQLFIDDLE: http://sqlfiddle.com/#!3/8c28c/5
SELECT DISTINCT t1.myts,
(SELECT COUNT(*)
FROM mytable t2
WHERE t2.myts = t1.myts
AND t2.id = 1) AS id_1_count,
(SELECT COUNT(*)
FROM mytable t2
WHERE t2.myts = t1.myts
AND t2.id = 2) AS id_2_count,
(SELECT COUNT(*)
FROM mytable t2
WHERE t2.myts = t1.myts) AS total
FROM mytable t1
If you add an id here though you would need another subquery
Could anybody guide me how to pivot my data. I have:
RowID Dimension Value
1 Country Italy
1 Year 2011
1 GDP 4
1 Population 6
2 Country Spain
2 Year 2011
2 GDP 7
2 Population 5
I want in a such way:
RowID Country Year GDP Population
1 Italy 2011 4 6
2 Spain 2011 7 5
P.S. I use MS SQL Server 2008 R2 Express Edition. I tried to use PIVOT but it returned many rows with NULL so I could not figure out.
You can use PIVOT for this. This can be hard-coded if you know all of the values:
select *
from
(
select rowid, dimension, value
from yourtable
) src
pivot
(
max(value)
for dimension in ([Country], [Year], [GDP], [Population])
) piv
See SQL Fiddle with Demo
Or of you do not have access to the PIVOT function, then you can use an aggregate with a CASE:
select rowid,
max(case when dimension = 'country' then value end) country,
max(case when dimension = 'Year' then value end) Year,
max(case when dimension = 'GDP' then value end) GDP,
max(case when dimension = 'Population' then value end) Population
from yourtable
group by rowid
See SQL Fiddle with Demo
If you have an unknown number of values, then you can use dynamic sql:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Dimension)
from yourtable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT rowid, ' + #cols + ' from
(
select rowid, dimension, value
from yourtable
) x
pivot
(
max(value)
for dimension in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
Im sure this is a simple technique although I can't find an answer so far!
I have
TIMESTAMP | POINTNAME | VALUE
2012-10-10 16:00:00 AHU01 20
2012-10-10 16:00:00 AHU02 25
2012-10-10 16:00:15 AHU01 26
2012-10-10 16:00:15 AHU02 35
etc... ( for approx 800 POINTNAMES)
with many pointnames I dont want to list each one in the 'IN' clause of the pivot 'FOR'
(as syntax given below) definition but would like to use perhaps a subquery.
So what I would like is all the POINTNAME values as columns with A TIMESTAMP AND VALUE column, so I will get one TIMESTAMP value and many columns with each POINTNAME, there is only one value per POINTNAME PER TIMESTAMP so I don't need to aggregate anything so just choose max anyway?
Something like:
SELECT [TIMESTAMP] FROM ( SELECT * FROM POINT_TABLE)
PIVOT( Max[Value] FOR [POINTNAME] IN (SELECT DISTINCT [POINTNAME] FROM POINT_TABLE)
would produce-
TIMESTAMP AHU01 AHU02
2012-10-10 16:00:00 20 25
2012-10-10 16:15:00 26 35
I realise it is probably no this simple but hopefully you get what I'm trying to achieve?
PIVOT SYNTAX:
SELECT <non-pivoted column>,
[first pivoted column] AS <column name>,
[second pivoted column] AS <column name>,
...
[last pivoted column] AS <column name>
FROM
(<SELECT query that produces the data>)
AS <alias for the source query>
PIVOT
(
<aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
IN ( [first pivoted column], [second pivoted column],
... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;
for dynamic number of columns you have to use dynamic SQL
declare
#cols nvarchar(max),
#stmt nvarchar(max)
select #cols = isnull(#cols + ', ', '') + '[' + T.POINTNAME + ']' from (select distinct POINTNAME from TABLE1) as T
select #stmt = '
select *
from TABLE1 as T
pivot
(
max(T.VALUE)
for T.POINTNAME in (' + #cols + ')
) as P'
exec sp_executesql #stmt = #stmt
SQL FIDDLE EXAMPLE
I need to know whether 'pivot' in MS SQL can be used for converting rows to columns if there is no aggregate function to be used. i saw lot of examples with aggregate function only. my fields are string data type and i need to convert this row data to column data.This is why i wrote this question.i just did it with 'case'. Can anyone help me......Thanks in advance.
You can use a PIVOT to perform this operation. When doing the PIVOT you can do it one of two ways, with a Static Pivot that you will code the rows to transform or a Dynamic Pivot which will create the list of columns at run-time:
Static Pivot (see SQL Fiddle with a Demo):
SELECT *
FROM
(
select empid, wagecode, amount
from t1
) x
pivot
(
sum(amount)
for wagecode in ([basic], [TA], [DA])
) p
Dynamic Pivot:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(wagecode)
FROM t1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT empid, ' + #cols + ' from
(
select empid, wagecode, amount
from t1
) x
pivot
(
sum(amount)
for wagecode in (' + #cols + ')
) p '
execute(#query)
Both of these will give you the same results
sample format
empid wagecode amount
1 basic 1000
1 TA 500
1 DA 500
2 Basic 1500
2 TA 750
2 DA 750
empid basic TA DA
1 1000 500 500
2 1500 750 750
THE ANSWER I GOT IS
SELECT empID , [1bas] as basic, [1tasal] as TA,[1otsal] as DA
FROM (
SELECT empID, wage, amount
FROM table) up
PIVOT (SUM(amt) FOR wgcod IN ([1bas], [1tasal],[1otsal])) AS pvt
ORDER BY empID
GO
Try this:
SELECT empid AS EmpID
, ISNULL(SUM(CASE wagecode WHEN 'basic' THEN Amount ELSE 0 END), 0) AS Basic
, ISNULL(SUM(CASE wagecode WHEN 'ta' THEN Amount ELSE 0 END), 0) AS TA
, ISNULL(SUM(CASE wagecode WHEN 'da' THEN Amount ELSE 0 END), 0) AS DA
FROM Employee
GROUP BY empid