Dynamic pivot - doesnt read the '+' sign - sql

Hi I am trying to run the below code, but getting the error below. telling me that the issue is due to ' + #Cols + ', however this code is referenced from the forums. Any help would be greatly appreciated. Thanks
Error
Msg 102, Level 15, State 1, Line 27
Incorrect syntax near ' + #Cols + '.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX);
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(year)
FROM [Reporting].[dbo].[FX_Table]
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
SELECT *
FROM
(
SELECT
[from],
[Year],
[FX]
FROM [Reporting].[dbo].[FX_Table] WHERE [To] = 'Euro'
GROUP BY
[from],
[Year],
[FX]
) AS S
PIVOT
(
SUM(FX)
FOR [year] IN ' + #Cols + '
)
AS PVT

How about this?
SELECT *
FROM (
SELECT [from],
[Year],
[FX]
FROM [Reporting].[dbo].[FX_Table]
WHERE [To] = 'Euro'
GROUP BY [from],
[Year],
[FX]
) AS S
PIVOT(SUM(FX) FOR [year] IN (
SELECT DISTINCT year
FROM [Reporting].[dbo].[FX_Table]
)) AS PVT
You don't have to create a variable where you will store all your values and then try to use IN to go over those values and filter them.
Also, if you create a NVARCHAR variable to hold all your years, then you will have to split all those values, by comma, to use them with IN (which would make your declaration of variable #Cols useless).
What you will have in your #Cols variable, the way you create it now, is something like below (ONE record which is the list of years):
But for your IN clause to work, you would need multiple records, each year a new record, like below:
I hope this solves your problem.

Related

trying to average column with CAST in PIVOT table- Incorrect syntax near '('

I am trying the Pivot function to get the following table-
split rows of TagID into columns, the TagValue of each TagID and DATEADD TimeStamp to display avg values every 5 minutes:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT ',' + QUOTENAME(TagID)
from table
group by TagID
order by TagID
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Top (500) DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS TimeStamp, ' + #cols + ' from
(
select TimeStamp, TagID , TagValue
from table
Group By TimeStamp, TagID, TagValue
) x
pivot
(
AVG(CAST(TagValue) AS DECIMAL(18,2))
for TagID in ( ' + #cols + ' )
) p '
execute(#query)
I am trying to create avg for the column TagValue.
After I used the CAST function as you can see above, the query displayed:
Msg 102, Level 15, State 1, Line 12
Incorrect syntax near '('.
although I cannot find what is wrong and which exact syntax is incorrect.
Would really appreciate some help here as Management studio doesn't show where the problem is.
I looked up online and normally the avg function is used like this:
AVG(TagValue) although it doesn't work on NVARCHAR column.
There was syntax issue with the CAST statement, also minor changes were made to sub query table x - please try the below code
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SELECT #cols = STUFF((SELECT ',' + QUOTENAME(TagID)
FROM table
GROUP BY TagID
ORDER BY TagID
FOR XML PATH(''), TYPE ).value('.', 'NVARCHAR(MAX)') ,1,1,'')
SET #query = 'SELECT TOP (500) DATEADD(minute,DATEDIFF(minute,0,TimeStamp)/5*5,0) AS TimeStamp, ' + #cols + ' from
(
select TimeStamp, TagID , TRY_CAST(TagValue AS DECIMAL(18,2)) AS [TagValue]
from table
Group By TimeStamp, TagID, TagValue
) x
pivot
(
AVG(TagValue)
for TagID in ( ' + #cols + ' )
) p '
EXEC(#query)
Change it to AVG(CAST(TagValue AS DECIMAL(18,2))) instead of
AVG(CAST(TagValue) AS DECIMAL(18,2)) in the pivot block.
i.e, you are using CAST(TagValue) AS DECIMAL(18,2)), but it should be CAST(TagValue AS DECIMAL(18,2))
You have issue with CAST Syntax. Use as below-
AVG(CAST(TagValue AS DECIMAL(18,2)))
You query shows table name is 'table'. Can you use the table name second bracket around as below-
FROM [table]

SQL Pivot Table from dynamic columns

I wrote this query to generate pivot table :
SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN (select ItemName_AR from WH_Items)
)AS pvt
but it cuases the following error in
Incorrect syntax near the keyword 'select'.
at this statment
FOR [ItemName] IN (select ItemName_AR from WH_Items)
Unfortunately, you may not use a select statement to provide the variety of values (unpivoted form)=columns(pivoted form). You may either use
IN ([value1],[value2]) etc
or consider a dynamic solution, here's a link:
SQL Server Dynamic Pivot Column Names
You cannot create Dynamic SQL PIVOT like that. You may try something like this...
DECLARE #cols AS NVARCHAR(max) = Stuff((SELECT DISTINCT ',' + Quotename(ItemName_AR)
FROM WH_Items
FOR xml path(''), type).value('.', 'NVARCHAR(MAX)'), 1, 1, '');
DECLARE #query AS NVARCHAR(max) = 'SELECT *
FROM (
SELECT
ItemName_AR as [ItemName],
NetValue as Amount
FROM view_WH_CompanyTransactionDtl
) as s
PIVOT
(
SUM(Amount)
FOR [ItemName] IN ('+ #cols +')
)AS pvt';
EXECUTE(#query)

SELECT inside pivot incorrect

SSMS is highlighting that something is wrong on the line FOR urlsByFilm.Media_Type_ID IN...
BEGIN
SELECT urlsByFilm.Film_ID, urlsByFilm.Media_Type_ID, urlsByFilm.Media_File_Name
FROM [dbo].[Film_Media_Item] urlsByFilm
PIVOT
(
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN (SELECT DISTINCT Media_Type_ID FROM [dbo].[Film_Media_Item])
) AS pivot
WHERE API_ID in (#API_IDs)
END
I cannot run this, can you help?
you can't have SQL expression in the IN clause, you need to specify the values.
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN
(SELECT DISTINCT Media_Type_ID FROM [dbo].[Film_Media_Item])
You need to use dynamic SQL to achieve what you are doing.
your query would like this, with dynamic SQL
DECLARE #cols NVARCHAR(2000)
SELECT #cols = STUFF(( SELECT DISTINCT
'],[' + Media_Type_ID
[dbo].[Film_Media_Item]
ORDER BY '],[' + Media_Type_ID
FOR XML PATH('')
), 1, 2, '') + ']'
DECLARE #query NVARCHAR(4000)
SET #query = N'SELECT Media_File_Name, '+
#cols +'
FROM
(SELECT urlsByFilm.Film_ID, urlsByFilm.Media_Type_ID, urlsByFilm.Media_File_Name
FROM [dbo].[Film_Media_Item] urlsByFilm)p
PIVOT
(
MAX(urlsByFilm.Media_File_Name)
FOR urlsByFilm.Media_Type_ID IN ( '+
#cols +' )
) AS pvt
WHERE API_ID in (#API_IDs)'
EXECUTE(#query)

Need SQL pivot assistance as I do not have an aggregate column

I have the following view I created that looks like this table.
Create Table #Temptable(
[Week number] int,
[Did Not meet minimum] int,
[Met minimum] int,
[exceeded minimum] int);
insert into #Temptable([Week number],[Did Not meet minimum],[Met minimum],[exceeded minimum])
values
(3,161,4,18),
(4,165,1,24),
(5,166,0,10)
I would like the output to be three lines so that I can create a trending report by week. I can populate a temp table to get the desired result but I would like to see if there is a better solution.
Label, week3, week4, week5
Did not meet minimum, 161, 165, 166
Met minimum, 4, 1, 0
Exceeded minimum, 18, 24, 10
If this is not possible from this data set I also have the source line item detail the view was created from. that dataset looks like this
techname,machinename,installdate,weeknumber
I made 3 scalar functions that aggregate by techname and week number so that I can get the Did not meet, Met, and exceeded install counts for each week.
Thank you in advance.
After getting the response from StuartLC I began to craft my own dynamic version I was close but as I was posting a response another kind person posted a working version. For everyone's benefit here is the sample code I put together it however is not working. If I copy the error text and just select the outputted query it does work properly.
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
SET #cols = STUFF((SELECT distinct ',' + QUOTENAME(c.[week number])
FROM SummarisedWeeklysums c
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Criteria, '+ #Cols +' FROM
(
SELECT
*
FROM
SummarisedWeeklysums
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] IN ('+#Cols+')
)pvt'
execute #query
This is quite similar to my answer here - basically you are looking for a full transpose. This can be done with an unpivot, followed by a pivot:
SELECT Criteria, [3] as Week3, [4] AS Week4, [5] AS Week5
FROM
(
SELECT
*
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] IN ([3],[4],[5])
)pvt;
Fiddle here
Also, if you need to do this for a bunch of unknown weeks (or criteria, I guess), you can look at the answer here which uses dynamic sql to build up the columns and execute the pivot.
The is based on StuartLC answer and link (credit to you) with scalability if extra weeks are added in the future:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME('Week'+cast([Week Number] as varchar))
FROM #Temptable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
select #query =
'SELECT *
FROM
(
SELECT
''Week''+cast([Week number] as varchar) as [Week number] , CriteriaCount , Criteria
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] in (' + #cols + ')
)pvt ;';
execute(#query);
Below is the same code, with the results moved into a temp table (as requested by user3275636) and then displayed:
DECLARE #cols AS NVARCHAR(MAX);
DECLARE #query AS NVARCHAR(MAX);
select #cols = STUFF((SELECT distinct ',' +
QUOTENAME('Week'+cast([Week Number] as varchar))
FROM #Temptable
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
, 1, 1, '');
select #query =
'select * into ##temp1 from (SELECT *
FROM
(
SELECT
''Week''+cast([Week number] as varchar) as [Week number] , CriteriaCount , Criteria
FROM
#Temptable
UNPIVOT
(
CriteriaCount
for Criteria in ([Did Not meet minimum],[Met minimum],[exceeded minimum])
) unpvt
) X
PIVOT
(
SUM(CriteriaCount)
for [Week Number] in (' + #cols + ')
)pvt ) as combi;';
execute(#query);
select * from ##temp1;

while converting column to row not able to fetch value from another table automatically

select *
from (
select vtid, convert(date, dtime) as Date from Transaction_tbl where locid = 5
) as vt
pivot (
count(vtid)
for vtid in (select vtid from VType_tbl)
) as pvt
while executing this query am getting error
Incorrect syntax near the keyword 'select'." and Incorrect syntax near
')'.
actually I have one more table,name= Vtype_table , How Can I load all vtid from vtype table in this query? I want to get output depend upon vtid.
Any help greatly appreciated.
Your PIVOT syntax is correct except you are using a SELECT statement inside your PIVOT.
You cannot use a SELECT statement inside the PIVOT IN clause to select column headers. It is required that the columns for the IN clause be known prior to executing the query.
If you are looking to generate a dynamic list of vtid values, then you will need to use dynamic SQL to get the result and the syntax will be similar to the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vtid)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select vtid, convert(date, dtime) as Date
from Transaction_tbl
where locid = 5
) d
pivot
(
count(vtid)
for vtid in (' + #cols + ')
) p '
execute(#query);
Edit, if you want the type names to appear then you should be able to use the following:
DECLARE #cols AS NVARCHAR(MAX),
#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(vt_name)
from VType_tbl
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set #query = 'SELECT Date, ' + #cols + '
from
(
select v.vt_name, convert(date, dtime) as Date
from Transaction_tbl t
inner join VType_tbl v
on t.vtid = v.vtid
where locid = 5
) d
pivot
(
count(vt_name)
for vt_name in (' + #cols + ')
) p '
execute(#query)
Note: I am guessing on the column name for VType_tbl