How To Set NULL is 0 in SQL Dynamic Pivot Query - sql

I developed one dynamic pivot table, and I set ISNULL = 0.00.
The query is given below
SELECT DISTINCT hdr.EmpNo,hdr.FirstName AS Name,
ISNULL(TBL.shortname,'')AS shortname,
ISNULL(TBL.Amount,0.00) AS Amount,
TBL.Adtype INTO #Temp FROM tbl1 AS hdr
LEFT JOIN tbl2 TBL ON TBL.EmpNo = hdr.EmpNo
DECLARE #Ded AS NVARCHAR(MAX)
SET #Ded = STUFF((SELECT ', ISNULL( ' + QUOTENAME(c.shortname) + ', 0.00 )AS ' +
QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Query = 'SELECT CAST(ROW_NUMBER() OVER(ORDER BY EmpNo ASC) AS
VARCHAR(100)) AS [S.No],EmpNo,Name,' + #Ded +' FROM #Temp
PIVOT(SUM(Amount) FOR shortname IN (' + #Ded + ')) AS PVTTable'
EXEC sp_executesql #Query
But it displays the following error, and line 3 doesn't not have a "(".
Msg 102, Level 15, State 1, Line 3
Incorrect syntax near '('.
Any help to solve this problem would be appreciated.

Problem is with #der variable use in in clause.
you are setting column name with isnull and in in clause, it is not supported.
Please try below query.
;with tbl1 as
(
select 1 EmpNo,'Emp1' FirstName
union all
select 2 EmpNo,'Emp2' FirstName
),
tbl2 as
(
select 'EMP1' shortname,100 Amount, 2 Adtype,1 EmpNo
union all
select 'EMP2' shortname,100 Amount, 2 Adtype,2 EmpNo
)
SELECT DISTINCT hdr.EmpNo,hdr.FirstName AS Name,
ISNULL(TBL.shortname,'')AS shortname,
ISNULL(TBL.Amount,0.00) AS Amount,
TBL.Adtype INTO #Temp FROM tbl1 AS hdr
LEFT JOIN tbl2 TBL ON TBL.EmpNo = hdr.EmpNo
DECLARE #Ded AS NVARCHAR(MAX)='' ,#Query AS NVARCHAR(MAX)=''
DECLARE #Wer AS NVARCHAR(MAX)=''
SET #Ded = STUFF((SELECT ', ISNULL( ' + QUOTENAME(c.shortname) + ', 0.00 )AS ' +
QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Wer = STUFF((SELECT ', ' + QUOTENAME(c.shortname) FROM (SELECT DISTINCT shortname FROM #Temp
WHERE ISNULL(shortname,'') <> '' AND Adtype = 2) AS c ORDER BY
shortname FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #Query = 'SELECT CAST(ROW_NUMBER() OVER(ORDER BY EmpNo ASC) AS
VARCHAR(100)) AS [S.No],EmpNo,Name,' + #Ded +' FROM #Temp
PIVOT(SUM(Amount) FOR shortname IN (' + #Wer + ')) AS PVTTable'
--print #Query
EXEC sp_executesql #Query

Related

SQL Server Dynamic Pivoting - Not Usal Pivot With Count

I need to Pivot Questions With Their Answers.The Desired Output of the pivot Query is below and the table structure too.
I have Created the SQL fiddle Here Sql Fiddle. I saw many examples of count with pivot but couldn't find something similar to this.
You simply need some joins to get the base data and a dynamic pivot to show the result in the desired format.
try the following:
drop table if exists #temp
--base table with all details
select s.ID SurveyID, s.SubmittedBy, sq.Question, sa.Answer
into #temp
from #Survey s
join #SurveyMaster sm on sm.ID = s.SurveyMasterID
join #SurveyQuestion sq on sq.SurveyMasterID = s.SurveyMasterID
join #SurveyAnswers sa on sa.SurveyQuestionID = sq.ID and sa.SurveyID = s.ID
--dynamic pivot
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.Question)
FROM #temp c
ORDER BY 1 DESC
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT SurveyID, SubmittedBy, ' + #cols + ' from
(
select SurveyID, SubmittedBy, Question, Answer
from #temp
) x
pivot
(
max(Answer)
for Question in (' + #cols + ')
) p '
--execution
execute(#query)
Please find the db<>fiddle here.
declare #sqlstring as varchar(max) = '';
SELECT
#sqlstring = STUFF((
SELECT distinct
',' + '[' + isnull(sq.Question, '''') + ']'
from
#surveyanswers sa
join
#SurveyQuestion sq
on sq.ID = sa.SurveyQuestionID
join
#survey sv
on sv.SurveyMasterID = sq.SurveyMasterID FOR XML PATH('')), 1, 1, '')
select
sa.SurveyID,
sv.SubmittedBy,
sq.Question,
sa.Answer into ##temp
from
#surveyanswers sa
join
#SurveyQuestion sq
on sq.ID = sa.SurveyQuestionID
join
#survey sv
on sv.SurveyMasterID = sq.SurveyMasterID
set
#sqlstring = 'SELECT SurveyID,SubmittedBy,' + #sqlstring + ' FROM (select * from ##temp ) t ' + ' PIVOT ( ' + ' max(Answer) FOR Question IN (' + #sqlstring + ' ) ) AS pivot_table' execute(#sqlstring);
RESULT:

Required pivot for below data structured

i have data in below format.
ID question answer
1 who A
1 where B
1 when C
1 how D
i required output as below
id who where when how
1 A B C D
You can try this using dynamic pivot query.
create table #temp (ID int, question varchar(20), answer char(1))
insert into #temp values
(1, 'who', 'A'),
(1, 'where', 'B'),
(1, 'when', 'C'),
(1, 'how', 'D')
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.question)
FROM #temp c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Id, ' + #cols + ' from
(
select Id
,question
, answer
from #temp
) x
pivot
(
max(answer)
for question in (' + #cols + ')
) p '
execute(#query)
Live Demo
use conditional aggregation
select id,
max(case when question='who' then answer end) as "who",
max(case when question='where' then answer end) as "where",
max(case when question='when' then answer end) as "when",
max(case when question='how' then answer end) as "how"
from table_name
group by id
You may try this.
DECLARE #column AS VARCHAR(MAX), #query AS VARCHAR(MAX);
SET #column = STUFF((SELECT distinct ',' + QUOTENAME(t.question) FROM table t FOR XML PATH(''), TYPE).value('.', 'VARCHAR(MAX)'),1,1,'')
set #query = 'SELECT Id, ' + #column + ' from
(
select Id, question, answer from table
) x
pivot
( max(answer) for question in (' + #column + ')
) p '
exec (#query)

Sql Pivoting on date

I am getting this error when trying to convert the below logic in to SQL query
Logic:
TRANSFORM First([SirName] & " - " & [SecondName]) AS Name
SELECT qry_Date.RoomNumber
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE (((qry_Date.RoomNumber) Is Not Null))
GROUP BY qry_Date.RoomNumber
PIVOT qry_Date.Date;
Below is what i have done so far
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(convert(NVARCHAR(MAX),qry_Date.Date,103))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT Name, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,qry_Date.Date
FROM Guest RIGHT JOIN qry_DateTemp ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)
Which results error
Msg 8114, Level 16, State 1, Line 9 Error converting data type
nvarchar to datetime2. Msg 473, Level 16, State 1, Line 9 The
incorrect value "13/12/2014" is supplied in the PIVOT operator. Msg
207, Level 16, State 1, Line 1 Invalid column name 'Name'.
My print #query output
SELECT Name, [01/12/2014],[02/12/2014],[03/12/2014],[04/12/2014],[05/12/2014],[06/12/2014],[07/12/2014],[08/12/2014],[09/12/2014],[10/12/2014],[11/12/2014],[12/12/2014],[13/12/2014],[14/12/2014],[15/12/2014],[16/12/2014],[17/12/2014],[18/12/2014],[19/12/2014],[20/12/2014],[21/12/2014],[22/12/2014],[23/12/2014],[24/12/2014],[25/12/2014],[26/12/2014],[27/12/2014],[28/12/2014],[29/12/2014],[30/12/2014],[31/12/2014]
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,qry_Date.Date
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( [01/12/2014],[02/12/2014],[03/12/2014],[04/12/2014],[05/12/2014],[06/12/2014],[07/12/2014],[08/12/2014],[09/12/2014],[10/12/2014],[11/12/2014],[12/12/2014],[13/12/2014],[14/12/2014],[15/12/2014],[16/12/2014],[17/12/2014],[18/12/2014],[19/12/2014],[20/12/2014],[21/12/2014],[22/12/2014],[23/12/2014],[24/12/2014],[25/12/2014],[26/12/2014],[27/12/2014],[28/12/2014],[29/12/2014],[30/12/2014],[31/12/2014])
) as p
One quick way to deal with this error is to convert all data to varchar(max) in same manner. After all dates will become header, so it should be string.
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(CAST(qry_Date.Date AS NVARCHAR(MAX)))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT RoomNumber, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Name
,qry_Date.RoomNumber
,CAST(qry_Date.Date AS NVARCHAR(MAX)) as [Date]
FROM Guest RIGHT JOIN qry_DateTemp ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(count(Name) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)
#DhruvJoshi did it as u Proposed and true i was in error. when i got my results i had to change the query to
DECLARE #cols AS NVARCHAR(MAX)
DECLARE #query AS VARCHAR(MAX)
SELECT #cols = STUFF((SELECT distinct top 100 percent
',' + QUOTENAME(CAST(qry_Date.Date AS NVARCHAR(MAX)))
FROM qry_Date
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)'),1,1,'');
SET #query = 'SELECT RoomNumber, ' + #cols + '
FROM
(SELECT [SirName] + '' - '' + [SecondName] AS Names
,qry_Date.RoomNumber
,CAST(qry_Date.Date AS NVARCHAR(MAX)) as [Date]
FROM Guest RIGHT JOIN qry_Date ON Guest.ID = qry_Date.GuestID
WHERE qry_Date.RoomNumber Is Not Null) as t
PIVOT
(MAX([Names]) FOR [Date] IN( ' + #cols + ')
) as p'
print #query
execute(#query)

Reverse Table In SQL

I have query:
SELECT DISTINCT temp.ID,request.RequestTypeID
FROM #MyTempTable6 as temp
JOIN dbo.FingerMachineUsers as fingeruser
ON temp.UserNo = fingeruser.ID
JOIN dbo.AppUsers as appuser
ON appuser.Id = fingeruser.UserId
LEFT JOIN dbo.Requests as request
ON request.UserId = fingeruser.UserId
And result of it:
How can I create table like this:
ID|RequestTypeID1|RequestTypeID2
1 | 4| 5
If you have only two values, then the simplest method is aggregation:
SELECT t.ID, MIN(r.RequestTypeID), MAX(r.RequestTypeID)
FROM #MyTempTable6 t JOIN
dbo.FingerMachineUsers fu
ON t.UserNo = fu.ID JOIN
dbo.AppUsers au
ON au.Id = fu.UserId LEFT JOIN
dbo.Requests r
ON r.UserId = fu.UserId
GROUP BY t.ID;
If you have have a variable number of values that you want to present, then the query is much more complicated.
PIVOT operator could be your best friend, if there are always only 2 values each...
Try this query...
Disclaimer: This code is purely based on this answer. (https://stackoverflow.com/a/10404455/6327676)
DECLARE #cols AS NVARCHAR(max),
#query AS NVARCHAR(max);
SET #cols = Stuff((SELECT DISTINCT ',' + Quotename(stff.requesttypeid)
FROM TableName stff
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET #query = 'SELECT ID, '+ #cols
+ ' FROM (select ID, RequestTypeId FROM TableName) x pivot (MAX(RequestTypeId) FOR RequestTypeId in ('
+ #cols + ')) p'
EXECUTE(#query)
Try this code it will work according to the result you want.
Firstly you need to dump #MyTempTable6 table into #temptable
then set RequestTypeID columns as comma seperated in #colums varible then set the columnname in #Requestcolumns variable,Then use pivot.
DECLARE #colums AS NVARCHAR(max)
DECLARE #Requestcolumns AS NVARCHAR(max)
DECLARE #query AS NVARCHAR(max);
SELECT DISTINCT temp.ID,request.RequestTypeID
into #temptable
FROM #MyTempTable6 as temp
JOIN dbo.FingerMachineUsers as fingeruser
ON temp.UserNo = fingeruser.ID
JOIN dbo.AppUsers as appuser
ON appuser.Id = fingeruser.UserId
LEFT JOIN dbo.Requests as request
ON request.UserId = fingeruser.UserId
SET #colums = Stuff((SELECT DISTINCT ',' +Quotename(tab.RequestTypeID)
FROM #temptable tab
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET #Requestcolumns = Stuff((SELECT DISTINCT ',' +Quotename(tab.RequestTypeID) +' AS ',+Quotename('RequestTypeID'+CONVERT(varchar(100),tab.RequestTypeID))
FROM #temptable tab
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, ''
)
SET #query = 'SELECT ID, '+#Requestcolumns
+ ' FROM (select ID, RequestTypeID FROM #temptable) x pivot (MAX(RequestTypeID) FOR RequestTypeID in ('
+ #colums + ')) p'
EXECUTE(#query)
DROP table #temptable

SQL Dynamic columns

select #cols =
STUFF((SELECT ',' + QUOTENAME(grade)
from #temp
group by grade
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select #colsRollup = STUFF((SELECT ', Sum(' + QUOTENAME(grade) + ') as '+QUOTENAME (grade)
from #temp
group by grade
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query
= 'SELECT * into #temp3 from
(
SELECT lob as "Vertical", '+ #colsRollup + '
FROM
(
SELECT lob,' + #cols + ' from
(
select lob,
grade,
asso_count
from #temp
) x
pivot
(
count(grade)
for grade in (' + #cols + ')
) p
) x1
GROUP BY lob with ROLLUP)x2'
execute(#query)
I am trying to create dynamic columns and insert it into a temporary table.
But it throws an error saying that #temp3 is not a valid object name. the code works if i dont try to insert the dynamic generated columns into a table.
If you execute the code and then try to access the #temp3table like:
execute(#query)
select * from #temp3
I would think it will have gone out of scope, which would explain the error message.
You could try to modify your query to include a SELECTlike:
SET #query = '
SELECT * INTO #temp3 FROM
(
SELECT lob as "Vertical", '+ #colsRollup + '
FROM
(
SELECT lob,' + #cols + ' from (select lob, grade, asso_count from #temp) x
PIVOT (count(grade) for grade in (' + #cols + ')) p
) x1
GROUP BY lob with ROLLUP
) x2; SELECT * FROM #temp3'
Note how the last line now includes ; SELECT * FROM #temp3
If you add that you should get the results back, if that is what you want.