This question already has answers here:
Get ROWS as COLUMNS (SQL Server dynamic PIVOT query)
(2 answers)
Closed 9 years ago.
I have the following basic SQL statement which uses the PIVOT command.
SELECT *
FROM
(
--select statement that creates my dataset
) s
PIVOT (Max(incidentcount) for dept in ([dept1],[dept2])) p
This does what I expect it to do, it gives me a count of incidents per reason with depts as my columns. My problem is the departments that I am using for my columns go from 1-60.
Is there anyway I can tell the query to use the column Department to populate the PIVOT in part. Obviously I want to avoid manually typing each department.
EDIT
This is the sql that creates my dataset that I use in the pivot...
SELECT Details, Department , count(*) NoIncidents
FROM myincidentdb
Group by Details, Department
EDIT 2
You will want to use dynamic sql to PIVOT this, your code will be similar to this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + QUOTENAME(dept)
from yourtablewithDepartments
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT *
from
(
<your query goes here>
) src
pivot
(
max(incidentcount)
for dept in (' + #cols + ')
) piv '
execute(#query)
If you post more details like table structure, etc then this can be refined to meet your needs.
Edit, based on your current query, it looks like you can use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX),
#colsNull AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(department)
from myincidentdb
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Details, ' + #cols + '
from
(
select Details, Department
from myincidentdb
) x
pivot
(
count(Department)
for Department in (' + #cols + ')
) p '
execute(#query)
See SQL Fiddle with Demo
Related
I would like to do a simple transpose in SQL Server and display 1 row and multiple columns. I have looked at pivot and unpivot and they seem too complex for this scenario. I am running a simple SQL query to get the rows:
select name
from sys.databases
where name like '%trn%'
Sample data:
prpc_trn
prpc_trn_arc
prpc_trn_IntegrationAuditDetails
prpc_trn_IntegrationAuditDetailsArchive
prpc_trn_Lumley
prpc_trn_PerformanceLoggingDetails
prpc_trn_PerformanceLoggingDetailsArchive
prpc_trn_prHistory
prpc_trn_prHistoryArchive
prpccpmi_trn
prpcref_trn
Based on my understanding of your question, this can only be achieved by PIVOT. But just using PIVOT is probably not the best since the columns are dynamic.
Based on the following article, I think using XML with PIVOT is better option than just using PIVOT.
I attempted to write a query based on this article for your requirement:
declare #cols as nvarchar(max), #query as nvarchar(max);
set #cols = stuff((select distinct ',' + quotename(c.[name])
from sys.databases c
where name like '%trx%'
for xml path(''), type).value('.', 'nvarchar(max)')
, 1, 1, '')
set #query = 'select * from (
select name from sys.databases ) x pivot (max(name) for name in (' + #cols + ')) p '
execute (#query)
This can be improved by using better values for column names. The above query will use the table name itself as the column name.
I'm trying to display exam results form simple database containing two tables tblStudents and tblExamResults.
tblstudents contains student ID and Full_Name columns
In tblexamResults columns are Student_id, Subject and Marks.
as in below Picture
1- Currently I am displaying Student results using this query
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
order by tblStudents.Full_Name
2 - And results looks like in the following picture:
3 - But what I want is to display each subject as row and get result of each subject below it
So that each student's result is displayed in the same row:
Student_Name sub1_result sub2_Result sub3_Result
Like in the following picture (Excel screenshot)
So:
How I can display data in that format?
Is that possible in SQL Server?
select fullname,[english] english, [history] history, [physics] physics
from
(
select fullname,subject,marks
from (yourquery)
) src
pivot
(
max(marks)
for subject in ([english], [history], [physics])
) piv;
or
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM (yourquery) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT fullname, ' + #cols + ' from
(
select fullname,subject,marks
from (your query)
) x
pivot
(
max(marks)
for subject in (' + #cols + ')
) p '
execute(#query)
fullname english history physics
a 85 70 60
i 60 100 89
s 90 90 99
Finally I've used next part of #Chanukya Answer with little Changes
in that Answer i was getting error at line 5 becouse of parentheses in FROM (yourquery) c
Declare #query nvarchar(max);
DECLARE #cols AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.subject)
FROM tblExamResults c ' parentheses Removed from (tblExamResults) c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'');
print(#cols)
set #query = '
SELECT *
FROM (
SELECT tblStudents.Full_Name, tblExamResults.Subject, tblExamResults.Marks
FROM tblExamResults INNER JOIN
tblStudents ON tblExamResults.Student_id = tblStudents.Student_ID
) as s
PIVOT
(
sum(marks) FOR subject IN ('+ #cols +')
)AS pvt'
;
execute(#query)
Trying to create a view with a PIVOT in it, can't figure out the syntax. The source view has three columns: ClientNameID, Item, and CountOfItem. I want ClientNameID to be the row, Item to be the column, and CountOfItem to be the value.
I figured it out:
SELECT clientnameid
FROM dbo.vAggregateSalesByCustomerAndItem
pivot (
Sum(countOfItem) FOR Item in ([Ring])
) PivotTable
The problem was syntax BUT I also learned that the dimensions (columns) must be hard-coded in the DML. I wanted to get the dimensions dynamically from a table, which is do-able in Excel, with a column range, but not here.
I think you should try this. its worked for you..
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT DISTINCT ',' + Item
from dbo.vAggregateSalesByCustomerAndItem
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT clientnameid ' + #cols + ' from
(
select clientnameid,countOfItem,Item
from dbo.vAggregateSalesByCustomerAndItem
) x
pivot
(
Sum(countOfItem)
for Item in (' + #cols + ')
) p '
execute(#query);
I'm using a pivot command and I've got it producing the desired output as written below:
SET ANSI_NULLS ON
GO
SET QUOTED_IDENTIFIER ON
GO
SELECT Id, IssuedCN, [EmailAddress], [ServerHostName], [ManagerEmail]
FROM (SELECT Id, IssuedCN, StringValue, Name
FROM dbo.certmetadata) AS Source
PIVOT(
MAX(StringValue)
FOR Name IN ([EmailAddress], [ServerHostName], [ManagerEmail])
)
AS PvtTable_1;
But the pivoted table names are going to be user defined. The current ones, [EmailAddress] [ServerHostName] [ManagerEmail], will probably stay there but could be changed or even non-existent. The user defined names are stored in a table but I can't seem to figure out how, if possible, to bring them into the above code.
I'm using server 2012.
If that doesn't make sense let me know and I can try to provide more detail.
Thanks!
If you are going to have an unknown number of columns, then you will need to look at using dynamic SQL. The basic syntax will be similar to this:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
-- get the list of columns
-- apply a filter on the columns here if needed
select #cols = STUFF((SELECT ',' + QUOTENAME(Name)
from dbo.certmetadata
group by name
order by name
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Id, IssuedCN,' + #cols + '
from
(
SELECT Id, IssuedCN, StringValue, Name
from dbo.certmetadata
) x
pivot
(
min(stringvalue)
for name in (' + #cols + ')
) p '
exec sp_executesql #query;
I have following table:
How to convert the above table into below structure? I tried using pivot table but couldn't get it to work.
You need to have to look up SQL PIVOT.
Check this fiddle
And the code:
SELECT *
FROM
(
SELECT Prodname,
pcode,
Biiledamt
FROM Product
) p
PIVOT
(
SUM (Biiledamt)
FOR Prodname IN ([Prod1],[Prod2],[Prod3],[Prod4])
) AS pvt
If you do not know beforehand the columns then you can check this fiddle which dynamically generates the columns to use.
The code for that is:
DECLARE #cols AS VARCHAR(MAX),
#query AS VARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',[' + Prodname +']'
FROM Product c
FOR XML PATH(''), TYPE
).value('.', 'VARCHAR(MAX)')
,1,1,'')
SET #query =
' SELECT *
FROM
(
SELECT Prodname,
pcode,
Biiledamt
FROM Product
) p
PIVOT
(
SUM (Biiledamt)
FOR Prodname IN (' + #cols + ')
) AS pvt
'
EXEC(#query)