SQL Server : 'Not valid identifier' when using PIVOT - sql

I have a temp table #temproles with data like this:
ID
Dept
RoleCode
RoleName
NameOf
123456
65576
1
CLP
Frank
123456
65576
2
SUH
Susan
234567
65578
2
SUH
Susan
234567
65576
13
CLH
Alison
I am trying to use PIVOT to return a dataset like this
ID
Dept
CLP
SUH
CLH
123456
65576
Frank
Susan
NULL
234567
65578
NULL
Susan
Alison
This is what I have so far:
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT
#ColumnName = STUFF((SELECT DISTINCT ',' + QUOTENAME(rolename, '''')
FROM #temproles
GROUP BY id, rolename
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SET #DynamicPivotQuery =
N'SELECT id, dept,' + #ColumnName + N' FROM
(
SELECT id, dept, rolename, nameOf
FROM #temproles
) x
PIVOT
(
ISNULL(nameOf, '''')
FOR rolename IN (' + #ColumnName + N')
) p'
EXEC sp_executesql #DynamicPivotQuery
This returns the following error:
Msg 102, Level 15, State 1, Line 9
Incorrect syntax near 'BDA'.
I previously was using EXEC #DynamicPivotQuery but got an error where the:
name of N'SELECT id, dept, etc.. was not a valid identifier.
My understanding is this was not correct so I changed it to EXEC sp_executesql #DynamicPivotQuery. Any help would be greatly appreciated!
For reference
SELECT STUFF((SELECT DISTINCT ',' + QUOTENAME(cdservicingrolecode, '''')
FROM #JLtemproles
GROUP BY uniqpolicy, cdservicingrolecode
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
returns
'BDA','BDP','CMW','BRC','CXA','CXH','BRP','SUH','CXP','BDH','CLP','BDL','PLH','CLH','SUP','PLP','BIP','BDS','CMP','CLA'

I was able to fix the query. The PIVOT needs an aggregate function, so ISNULL() will not work. I replaced it with MIN(). The role names also need to be enclosed in brackets rather than quotes. Here is the code along with my temp table test.
DROP TABLE IF EXISTS #temproles
CREATE TABLE #temproles (ID INT, Dept INT, RoleCode INT, RoleName VARCHAR(3), NameOf VARCHAR(10))
INSERT INTO #temproles
SELECT 123456, 66576, 1, 'CLP', 'Frank'
UNION ALL SELECT 123456, 66576, 2, 'SUH', 'Susan'
UNION ALL SELECT 234567, 65578, 2, 'SUH', 'Susan'
UNION ALL SELECT 234567, 65576, 13, 'CLH', 'Alison'
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
SELECT #ColumnName = STUFF((SELECT DISTINCT ',[' + rolename + ']'
FROM #temproles
GROUP BY id, rolename
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'),1,1,'')
SELECT #ColumnName
SET #DynamicPivotQuery =
N'SELECT id, dept,' + #ColumnName + N' FROM
(
SELECT id, dept, rolename, nameOf
FROM #temproles
) x
PIVOT
(
MIN(nameOf)
FOR rolename IN (' + #ColumnName + N')
) p'
EXEC sp_executesql #DynamicPivotQuery

Related

Pivot for Unknown number of values in description- SQL Server 2008

May some one please help me how to get the result in SQL SERVER 2008
Are you trying to do something like this:
IF OBJECT_ID('tempdb..#TABLE') IS NOT NULL
BEGIN;
DROP TABLE #TABLE;
END;
CREATE TABLE #TABLE
(
[Generic Name] varchar(15),
[Description]varchar(15)
)
INSERT #TABLE
SELECT 'RESISTOR', 'POWER' UNION ALL
SELECT 'RESISTOR', 'Type' UNION ALL
SELECT 'RESISTOR', 'DESIGN' UNION ALL
SELECT 'RESISTOR', 'Material' UNION ALL
SELECT 'OTHER', 'Other' UNION ALL
SELECT 'OTHER', 'Material';
DECLARE #cols NVARCHAR(MAX)
,#query NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Description)
from #TABLE
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT [Generic Name], ' + #cols + '
FROM
(
SELECT [Generic Name], [Generic Name] AS [BaseName], [Description]
from #TABLE
) DS
pivot
(
COUNT([BaseName])
for [Description] in (' + #cols + ')
) p '
SELECT #query
execute(#query)
This will show you the count (but if you have only one record for each description it will be only true/have or false/not have) of each generic name.
Try the below change in your query
set #query = 'SELECT ' + #cols + ' from
(
select [Generic Name], Description
from #TABLE
) x
pivot
(
MAX([Generic Name])
for Description in (' + #cols + ')
) p '
Since you are pivoting the records, there won't be a column [Generic Name] -- I Don't see any such column in the table structure so I'm assuming that you need to column Base Name-- so, the #Cols parameter is enough
Please Check the Demo here

How To Set NULL is 0 in SQL Dynamic Pivot Query

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

How to pivot rows into colums dynamically SQL Server

I have a request which returns something like this:
--------------------------
Tool | Week | Value
--------------------------
Test | 20 | 3
Sense | 20 | 2
Test | 19 | 2
And I want my input to look like this:
-------------------------
Tool | W20 | W19
-------------------------
Test | 3 | 2
Sense | 2 | null
Basically, for every week I need to have a new column. The number of week and of tools is dynamic.
I have tried many things but nothing worked. Anybody have a solution ?
Try this
CREATE table #tst (
Tool varchar(50), [Week] int, Value int
)
insert #tst
values
('Test', 20, 3),
('Sense', 20,2),
('Test', 19, 2)
Here is the Dynamic Query:
DECLARE #col nvarchar(max), #query NVARCHAR(MAX)
SELECT #col = STUFF((SELECT DISTINCT ',' + QUOTENAME('W' + CAST([Week] as VARCHAR))
from #tst
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SET #query = '
SELECT *
FROM (
SELECT Tool,
Value,
''W'' + CAST([Week] as VARCHAR) AS WeekNo
FROM #tst
) t
PIVOT
(
MAX(t.Value)
FOR WeekNo IN (' + #col + ')
) pv
ORDER by Tool'
EXEC (#query)
Result
Tool W20 W19
=================
Sense 2 NULL
Test 3 2
IF OBJECT_ID('tempdb..#temp') IS NOT NULL
DROP TABLE #temp
CREATE TABLE #temp
( Tool varchar(5), Week int, Value int)
;
INSERT INTO #temp
( Tool , Week , Value )
VALUES
('Test', 20, 3),
('Sense', 20, 2),
('Test', 19, 2)
;
DECLARE #statement NVARCHAR(max)
,#columns NVARCHAR(max),
#col NVARCHAR(max)
SELECT #columns = ISNULL(#columns + ', ', '') + N'[' +'w'+ tbl.[Week] + ']'
FROM (
SELECT DISTINCT CAST([Week] AS VARCHAR)[Week]
FROM #temp
) AS tbl
SELECT #statement = 'SELECT *
FROM
(
SELECT
Tool , ''w''+ CAST(Week AS VARCHAR) week , Value
FROM
#Temp
) src
PIVOT(MAX(Value)for Week in (' + #columns + ')) as pvt
'
EXEC sp_executesql #statement = #statement
This is how I would do it ... If I understood your question correctly
if object_id('tempdb..#InputTool') is not null drop table #InputTool
create table #InputTool (Tool nvarchar(10), [20] int, [19] int)
insert into #InputTool (Tool, [20], [19])
values
('Test', 3, 2),
('Sense', 2, null)
declare #cols nvarchar(max)
select #cols = STUFF((SELECT ',' + QUOTENAME(name)
from tempdb.sys.columns
where object_id = object_id('tempdb..#InputTool')
and Column_id > 1
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #sqlquery nvarchar(max) =
'select Tool, Weeks, Value from (
select * from #InputTool
) as it
UNPIVOT
(
Value FOR Weeks IN (' + #cols + ')
) AS Weeks
order by Weeks desc'
execute (#sqlquery);
Give it a shot and let me know if it worked

Dynamic Pivot Error in sql server

I used the above code from the link. But I recieve an error as
Msg 8156, Level 16, State 1, Line 14 The column 'Factory' was
specified multiple times for 'p'
Efficiently convert rows to columns in sql server
Here is my table :
TEST
ID score Check TotalofScore
------ ----- ------- ------------
867439 1 factory 1
867439 1 Plant 1
867442 1 factory 1
867442 1 Plant 1
923991 1 Warehouse 1
923991 1 Plant 1
923930 1 factory 1
923930 1 Plant 1
923101 1 Warehouse 1
923101 1 Plant 1
Here's my try
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check],
[ID]
ORDER BY [ID]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
Expected Result :
ID TotalofScore factory Plant Warehouse
------ ------------ ------- ----- ---------
867439 1 1
867439 1 1
867442 1 1
867442 1 1
923991 1 1
923991 1 1
923930 1 1
923930 1 1
923101 1 1
923101 1 1
As mentioned in Error You cannot specify same column name more than once in Pivot like
..pivot (SUM (T.[score])
for T.[check] in ([factory,[Plant],[factory]..))p
Change your #cols initialization like this
SELECT #cols = Stuff((SELECT DISTINCT ',' + Quotename([check])
FROM TEST
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Or
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
Update : To convert the Dynamic Pivot into procedure and insert the result into new table
create procedure dbname.schemaname.DynamicPivotProcedure
as
begin
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = Stuff((SELECT ',' + Quotename([check])
FROM TEST
GROUP BY [Check]
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)'), 1, 1, '')
SET #query = N'SELECT ID, [Total Of Score],' + #cols + N' from
(SELECT TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM TEST) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N') ) p '
EXEC Sp_executesql #query;
end
go
sp_configure 'Show Advanced Options', 1
GO
RECONFIGURE
GO
sp_configure 'Ad Hoc Distributed Queries', 1
GO
RECONFIGURE
GO
IF OBJECT_ID('tempdb..#MyTempTable') IS NOT NULL
begin
DROP TABLE #MyTempTable
end
SELECT * INTO #MyTempTable FROM
OPENROWSET('SQLNCLI', 'Server=(local)\SQL2008;Trusted_Connection=yes;',
'EXEC dbname.schemaname.DynamicPivotProcedure')
SELECT * FROM #MyTempTable
Remove the Id from GROUP BY and ORDER By clause. So that you get the DISTINCT Check columns.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME([check])
from #Sample
group by [Check]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = N'SELECT ID, [Total Of Score], ' + #cols + N' from
(
SELECT
TEST.[ID],
Score,
[check],
[Total Of Score] = Count(TEST.Score) over(partition by [ID], [score], [check])
FROM #Sample AS TEST
) T
pivot
(
SUM (T.[score])
for T.[check] in (' + #cols + N')
) p '
exec sp_executesql #query;

SQL Server 2008 - Dynamic Pivot on one column, group by another, maintain reference to third

I've just started learning SQL and am struggling with dynamically transposing a three column table correctly. I previously hard coded the query, but now need it to be dynamic as the values in my pivot column may change in the future.
Here's my starting point:
questionid | DebriefingQuestionResults | OperationSessionRecordID
------------------------------------------------------------------
32 | 3 | 8071
34 | 0 | 8071
36 | 1 | 8071
32 | 2 | 8074
34 | 6 | 8074
36 | 5 | 8074
And here's what I want to produce:
OperationSessionRecordID | 32 | 34 | 36
----------------------------------------------
8071 | 3 | 0 | 1
8074 | 2 | 6 | 5
There are only three [questionid] values (32, 34, and 36), at the moment but this may change in the future, hence wanting a dynamic query. There are about 12000 [OperationSessionRecordID] values. All columns are of the type int not null.
Based on this answer I've got this so far, but am not sure how to proceed as it throws the error shown below.
USE training_db
--Test to see if table exists, if so drop ready for creation--
IF OBJECT_ID('TheatreMan.DebriefingQuestionsResultsPivoted','U') IS NOT NULL
DROP TABLE TheatreMan.DebriefingQuestionsResultsPivoted
--Declare query and variable names--
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get Distinct values of the PIVOT column--
SET #ColumnName = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.questionid)
FROM dbo.DebriefingQuestionsResultsTEMP
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
'SELECT OperationSessionRecordID, ' + #ColumnName + '
(select questionid,
DebriefingQuestionResults
OperationSessionRecordID
FROM dbo.DebriefingQuestionsResultsTEMP)
x
PIVOT (
min(DebriefingQuestionResults)
for questionid in (' + #ColumnName + ')
)
AS PIV'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
When I run this it throws this error, so something's obviously wrong with my #ColumnName variable, but I can't work out what it is.
Msg 4104, Level 16, State 1, Line 9
The multi-part identifier "c.questionid" could not be bound.
Any help would be most appreciated!
SB
This should work:
declare #collist nvarchar(max)
SET #collist = stuff((select distinct ',' + QUOTENAME(questionid)
FROM #t -- your table here
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
declare #q nvarchar(max)
set #q = '
select OperationSessionRecordID, ' + #collist + '
from (
select OperationSessionRecordID, DebriefingQuestionResults, questionid
from (
select *
from #t -- your table here
) as x
) as source
pivot (
sum(DebriefingQuestionResults)
for questionid in (' + #collist + ')
) as pvt
'
exec (#q)
try this, I think you just misspelled variable name.
USE training_db
--Test to see if table exists, if so drop ready for creation--
IF OBJECT_ID('TheatreMan.DebriefingQuestionsResultsPivoted','U') IS NOT NULL
DROP TABLE TheatreMan.DebriefingQuestionsResultsPivoted
--Declare query and variable names--
DECLARE # USE training_db
--Test to see if table exists, if so drop ready for creation--
IF OBJECT_ID('TheatreMan.DebriefingQuestionsResultsPivoted','U') IS NOT NULL
DROP TABLE TheatreMan.DebriefingQuestionsResultsPivoted
--Declare query and variable names--
DECLARE #QuestionPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get Distinct values of the PIVOT column--
SET #ColumnName = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.questionid)
FROM dbo.DebriefingQuestionsResultsTEMP
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
'SELECT OperationSessionRecordID, ' + #ColumnName + '
(select questionid,
DebriefingQuestionResults
OperationSessionRecordID
FROM dbo.DebriefingQuestionsResultsTEMP
ORDER BY OperationSessionRecordID ASC
)x
PIVOT
(
min(DebriefingQuestionResults)
for questionid in (' + #ColumnName + ')
)
AS PIV'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery AS NVARCHAR(MAX)
DECLARE #ColumnName AS NVARCHAR(MAX)
--Get Distinct values of the PIVOT column--
SET #ColumnName = STUFF((SELECT DISTINCT ',' + QUOTENAME(c.questionid)
FROM dbo.DebriefingQuestionsResultsTEMP
FOR XML PATH (''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
'SELECT OperationSessionRecordID, ' + #ColumnName + '
(select questionid,
DebriefingQuestionResults
OperationSessionRecordID
FROM dbo.DebriefingQuestionsResultsTEMP)
x
PIVOT (
min(DebriefingQuestionResults)
for questionid in (' + #ColumnName + ')
)
AS PIV'
ORDER BY OperationSessionRecordID ASC
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery