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
Related
I am new here.
I have the fallowing data on a table:
And I need to get the fallowing result:
I am using the fallowing SQL query:
SQL Query
DECLARE #sql AS NVARCHAR(MAX)=''
DECLARE #cols AS NVARCHAR(MAX)=''
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Date)
FROM vRecords
ORDER BY ',' + QUOTENAME(Date)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #sql = N'
SELECT EmpID, Name, ' + #cols + '
FROM (
select EmpID,Name,Date,Time
from vRecords
) a
PIVOT(COUNT(Time) FOR Date IN (' + #cols + ')) p'
EXECUTE(#sql)
What I need to accomplish is to know how many TIMES the user have a record on each DATE
But I am getting wrong result:
What am I doing wrong?
Sorry for all the links but because I am new I can't embed images.
I figured the issue.
All the problem was related to date format.
The columns were been generated with this format 2018-09-12 and the data was on this format 12/09/2018.
Any way, thanks for the comments.
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 have some tables with more than 700 columns/1000 columns.
Now I want to display all columns from this table to ISNULL(col1,0) format because when I use PIVOT/UNPIVOT and if there are some NULL values then they wont be converted to NULL and becomes empty strings. So I am trying to replace those NULLs with 0.
In this example I used sysobjects table so that you can try it in your ssms.
The result of this is incomplete as neither VARCHAR(MAX) nor NVARCHAR(MAX) is enough. How do I get all rows rather than few rows here?
DECLARE #colsUnpivot VARCHAR(MAX)
SET #colsUnPivot = STUFF((
SELECT ',' + 'ISNULL(' + QUOTENAME(name) + ', 0) AS '
+ QUOTENAME(name)
FROM sysobjects t
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
PRINT #colsUnPivot
set #query = 'SELECT id,code_name,lkp_value
FROM
(
SELECT unitid,institution,city,state,zip, '+ #colsUnpivot+'
FROM sysobjects) AS cp
UNPIVOT (lkp_value for code_name IN ('+#colsUnPivot+')
) AS up'
--PRINT #Query
--PRINT #Query1
exec(#query)
I mean the code above does not make sense but I can not produce same thing that I have as i have to use sysobjects here.
But above code is throwing an error:
Msg 102, Level 15, State 1, Line 6
Incorrect syntax near '('.
And that's because there is so much data and it's being truncated.
Here is what my PRINT says,
,ISNULL([opd_
So I still think its truncating.
Your problem is that the PRINT command will truncate the data for display in SSMS.
I would suggest leaving it as XML and doing a SELECT, if you just need to see the data in SSMS without truncating:
DECLARE #colsUnpivot xml
SET #colsUnPivot = (SELECT ',' + 'ISNULL(' + QUOTENAME(name) + ', 0) AS '
+ QUOTENAME(name)
FROM sysobjects t
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
SELECT #colsUnPivot
SSMS treats XML output differently and has a higher threshold for truncating the data.
Use SELECT instead of print in your SQL.
SELECT #colsUnPivot
Also, make sure that these values are maxed out in Results to Grid:
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
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;