Simple transpose in SQL Server - sql

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.

Related

change column names in a dynamic pivot table result

I have a tsql dynamic pivot table query that works fine although I´m not happy with the column names in the final output.
To make it work, the user has to select up to 20 fruit names from a list of 200 fruit names. Then I build the pivot table so I end up with different column names everytime the select is run.
For example:
First time the column names are: apple, orange and pear
Second time is: .orange, banana, kiwi and apple
My question is: Is there a posibility to have static names, like for example: name of the first column always "col_1", second column "col_2" etc?
The select statement is as follows:
DECLARE #idList varchar(800)
DECLARE #sql nvarchar(max)
SELECT #idList = coalesce(#idList + ', ', '') + '['+ltrim(rtrim(id_producto)) +']'
from gestor_val_pos
group by id_producto order by id_producto
SELECT #sql = 'select * from #correlaciones pivot (max (correl)
for codigo2 in (' + #IDlist + ')) AS pvt order by codigo1;'
exec sp_executeSQL #sql
sure.. just created a new variable to hold the column aliases and Row_Number to get the column number.
DECLARE #idList varchar(800)
DECLARE #idListAlias varchar(800)
DECLARE #sql nvarchar(max)
SELECT
#idList = coalesce(#idList + ', ', '') + '['+ltrim(rtrim(id_producto)) +']',
#idListAlias = coalesce(#idListAlias + ', ', '') + '['+ltrim(rtrim(id_producto)) +'] as col_' + CONVERT(VARCHAR(10), ROW_NUMBER() OVER(ORDER BY id_producto))
from gestor_val_pos
group by id_producto order by id_producto
SELECT #sql = 'select ' + #idListAlias + ' from #correlaciones pivot (max (correl)
for codigo2 in (' + #IDlist + ')) AS pvt order by codigo1;'
exec sp_executeSQL #sql
Yes, but it'll make your query significantly more complex.
You'll need to return a list of the possible column names generated from #IDList and convert that into a SELECT clause more sophisticated than your current SELECT *.
When you've got that, use some SQL string splitting code to convert the #IDList into a table of items with a position parameter. Append AS <whatever> onto the end of any you want and use the FOR XML PATH trick to flatten it back, and you've got a SELECT clause that'll do what you want. But, as I said, your code is now significantly more complicated.
As an aside - I really hope that #idList is either completely impossible for any user input to ever reach or hugely simplified from your real code for this demonstration. Otherwise you've got a big SQL injection hole right there.

Dynamic Query Restructuring for View

I have created a dynamic SQL query that I want to use as a view, however, the query is dependent on using 'DECLARE' statements. I have tried unsuccessfully to restructure it without the 'DECLARE' statements, but can't quite get it right. I am using SQL Server Express 2014 and would appreciate any and all help.
DECLARE #query nvarchar(MAX)
DECLARE #Name nvarchar(MAX)
select #Name = STUFF((SELECT distinct ',' + QUOTENAME(Name)
FROM [dbo].[ObjectView]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = ' SELECT * from
(
select *
from [dbo].[ObjectView]
)t
pivot (MAX(Value) for Name IN (' +#Name+ ')) AS PivotTable'
execute(#query)
You may have to play with the XML syntax. I'm pretty rusty.
create view viewname as
select * --< you really should call out the fields, here...
from(
select * --< ...and here.
from ObjectView
t
pivot( MAX( Value ) for Name in(
select distinct QUOTENAME( Name )
FROM ObjectView
FOR XML PATH )
) AS PivotTable

Pull cell data from a table for use in a stored procedure

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;

SQL Stuff Function with Variable in SQL Server

I am trying to generate an Pivot table with SQL (SQL Server 2008). To get the column list I am using stuff function which works great if we use it with SQL.
Although due to dynamic nature of Pivot structure (selection by user) I want to make column name set as a variable. I can catch correct SQL Stuff syntax but not able to execute it. Any Idea?
See code example as below:
Working Code:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Station)
from #ResultCrosstab
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
Select #cols
Not Working Code as below
Declare #ColumnName varchar(100)
set #ColumnName='Station'
DECLARE #cols1 AS NVARCHAR(MAX)
DECLARE #queryCol AS NVARCHAR(MAX)
set #queryCol='STUFF((SELECT distinct '','' + QUOTENAME(' + #ColumnName + ')
from #ResultCrosstab
FOR XML PATH(''), TYPE
).value(''.'', ''NVARCHAR(MAX)'')
,1,1,'''')'
Select #queryCol
Select #cols1=(#queryCol)
Not Working code returns the sql query itself rather than result.
Any Idea or suggestions?
Cheers
Hardeep
Execute the query rather than select it. Select #queryCol will return the value of #queryCol
Select #cols1=(#queryCol) will put the value of #queryCol into #cols1
You will need to EXEC SP_EXECUTESQL(#queryCol) or EXEC(#queryCol) to execute the actual query

PIVOT for in many column headers using field [duplicate]

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