SQL Server Syntax Error on PIVOT - sql-server

Can anyone please help me with the PIVOT table syntax error as I am using this for the First time.
DECLARE #sql AS varchar(max)<br/>
DECLARE #pivot_list AS varchar(max) <br/>
DECLARE #select_list AS varchar(max) <br/>
SELECT #pivot_list = COALESCE(#pivot_list + ', ', '') + '[' + CONVERT(varchar, STATE_NAME) + ']'<br/>
,#select_list = COALESCE(#select_list + ', ', '') + '[' + CONVERT(varchar, STATE_NAME) + '] AS [' + CONVERT(varchar, STATE_NAME) + ']'
FROM (
SELECT DISTINCT name as STATE_NAME
FROM k12_dms_states
) AS PIVOT_CODES
SET #sql = '
SELECT COUNT(k12_dms_contacts_institution_jobtitles.id) as total_count
,k12_dms_job_titles.title as job_title,' + #select_list + '
FROM k12_dms_institution_master
INNER JOIN k12_dms_contacts_institution_jobtitles ON k12_dms_institution_master.id = k12_dms_contacts_institution_jobtitles.inst_id
INNER JOIN k12_dms_job_titles ON k12_dms_job_titles.id = k12_dms_contacts_institution_jobtitles.job_title_id
GROUP BY k12_dms_job_titles.title
PIVOT (
total_count
FOR STATE_NAME IN (
' + #pivot_list + '
)
) AS pvt
'
PRINT #sql
EXEC (#sql)
I am getting this error: -
Msg 156, Level 15, State 1, Line 8
Incorrect syntax near the keyword 'PIVOT'.

PIVOT belongs in the FROM clause. It needs to occur before any GROUP BY clause.
(Further edits based on commenting, to try to correct):
SET #sql = '
SELECT
k12_dms_job_titles.title as job_title,' + #select_list + '
FROM k12_dms_institution_master
INNER JOIN k12_dms_contacts_institution_jobtitles ON k12_dms_institution_master.id = k12_dms_contacts_institution_jobtitles.inst_id
INNER JOIN k12_dms_job_titles ON k12_dms_job_titles.id = k12_dms_contacts_institution_jobtitles.job_title_id
PIVOT (
COUNT(k12_dms_contacts_institution_jobtitles.id)
FOR STATE_NAME IN (
' + #pivot_list + '
)
) AS pvt
'

Related

Sort COALESCE generated columns in a dynamic pivot table

I would like to sort the columns, but I get the following error:
The ORDER BY clause is invalid in views, inline functions, derived tables, subqueries, and common table expressions, unless TOP, OFFSET or FOR XML is also specified.
The years select query returns them in order, but they are shuffled when handled by the COALESCE function.
How can I prevent this? Or even better, control the sorting?
NOTE: The sorting works if I put a TOP 10 in the subquery. Super weird...
-- variables
DECLARE #sql AS varchar(max)
DECLARE #pivot_list AS varchar(max) -- Leave NULL for COALESCE technique
DECLARE #select_list AS varchar(max) -- Leave NULL for COALESCE technique
-- columns
SELECT -- top 10 makes the sorting work
-- [2018], [2020], [2017], [2019] -- not ordered
#pivot_list = COALESCE(#pivot_list + ', ', '') + '[' + PIVOT_COLUMN + ']',
#select_list = COALESCE(#select_list + ', ', '') + 'ISNULL([' + PIVOT_COLUMN + '], 0) as [' + PIVOT_COLUMN + ']'
FROM (
SELECT
-- 2017, 2018, 2019, 2020 -- ordered
cast(year(addate) as nvarchar(4)) as PIVOT_COLUMN
FROM tHE_Move M
where addate >= '01.01.2017'
group by year(addate)
-- order by year(addate) asc -- <-------------------------------------- doesn't work
) as PIVOT_COLUMNS
-- query
SET #sql = '
; WITH PivotData AS (
select
shop,
y AS PIVOT_COLUMN,
sum(revenueNoVAT) revenueNoVAT
from (
SELECT
SS.acName2 shop,
year(m.addate) y,
MI.anPVVATBase revenueNoVAT
FROM tHE_MoveItem MI
JOIN tHE_Move M ON MI.acKey = M.acKey
JOIN tHE_SetSubj SS ON M.acIssuer = SS.acSubject
WHERE m.acDocType in (
' + '''3210''' + ',
' + '''3220''' + ',
' + '''3230''' + ',
' + '''3240''' + '
)
) t1
group by
shop,
y
)
SELECT shop, ' + #select_list + '
FROM PivotData
PIVOT (
sum(revenueNoVAT)
FOR PIVOT_COLUMN
IN (' + #pivot_list + ')
) piv
order by shop desc
'
-- execution
EXEC (#sql)

Using sub-query to generate case statements

What i am trying to accomplish is comparing two rows to each other pointing out the differences from row to row. Each row has quite a few columns and I was trying to make it easily visible for which ones had changed. Code below is my thoughts, but I know this won't work, but is a start.
SELECT
(SELECT concat('Case WHEN T1.', column_name, ' <> T2.', column_name, ' THEN ''', column_name, ' Changed Values('' + CONVERT(varchar(100), T1.', column_name, ') + '', '' + CONVERT(varchar(100), T2.', column_name, ') + '')'' ELSE '''' END AS ', column_name)
FROM information_schema.columns
WHERE table_name = 'Table')
FROM
(
SELECT * FROM Table
WHERE ID = '13'
) AS T1
JOIN
(
SELECT * FROM Table
WHERE ID = '2006'
) AS T2
ON T1.CreateTimeStamp = T2.CreateTimeStamp
I got the idea because below this works fine, but I would like this to be potentially reusable code for other table without having to type out tens or hundreds of columns each time.
SELECT
Case WHEN T1.R1<> T2.R1 THEN 'Changed Values(' + CONVERT(varchar(100),T1.R1) + ', ' + CONVERT(varchar(100),T2.R1) + ')' ELSE '' END AS R1,
Case WHEN T1.R2<> T2.R2 THEN 'Changed Values(' + CONVERT(varchar(100),T1.R2) + ', ' + CONVERT(varchar(100),T2.R2) + ')' ELSE '' END AS R2
FROM
(
SELECT * FROM Table
WHERE ID = '13'
) AS T1
JOIN
(
SELECT * FROM Table
WHERE ID = '2006'
) AS T2
ON T1.CreateTimeStamp = T2.CreateTimeStamp
For the this example please assume CreateTimeStamp always equals each other between the two rows.
You would need to create the whole query as dynamic SQL. Note that I'm using QUOTENAME() to prevent SQL Injection from weirdly named columns. I'm also trying to keep a format for the code, so I won't get headaches when debugging.
DECLARE #SQL NVARCHAR(MAX);
SELECT #SQL = N' SELECT ' + NCHAR(10)
--Concatenate all columns except ID and CreateTimeStamp
+ STUFF(( SELECT REPLACE( CHAR(9) + ',CASE WHEN T1.<<ColumnName>> <> T2.<<ColumnName>> ' + CHAR(10)
+ CHAR(9) + CHAR(9) + 'THEN ''Changed Values('' + CONVERT(varchar(100),T1.<<ColumnName>>) + '', '' + CONVERT(varchar(100),T2.<<ColumnName>>) + '')'' ' + CHAR(10)
+ CHAR(9) + CHAR(9) + 'ELSE '''' END AS <<ColumnName>>', '<<ColumnName>>', QUOTENAME(COLUMN_NAME)) + NCHAR(10)
FROM INFORMATION_SCHEMA.COLUMNS
WHERE TABLE_NAME = 'Table'
AND COLUMN_NAME NOT IN( 'ID', 'CreateTimeStamp')
FOR XML PATH(''), TYPE).value('./text()[1]', 'nvarchar(max)'), 2, 1, '') + NCHAR(10)
--Add rest of the query
+ 'FROM Table AS T1 ' + NCHAR(10)
+ 'JOIN Table AS T2 ON T1.CreateTimeStamp = T2.CreateTimeStamp ' + NCHAR(10)
+ 'WHERE ID = #ID1 ' + NCHAR(10)
+ 'AND ID = #ID2;'
--PRINT for debugging purposes
PRINT #SQL;
--Execute the dynamic built code
EXECUTE sp_executesql #SQL,
N'#ID1 int, #ID2 int',
#ID1 = 13,
#ID2 = 2006;
The concatenation method is explained on this article.

How to add DISTINCT to a column in select query

Can you help me how to use DISTINCT in this query?
DECLARE #ReadData NVARCHAR(MAX);
SET #ReadData = 'SELECT ROW_NUMBER() OVER (ORDER BY RM.ReceiverDate) AS [S. No.]
,DISTINCT RM.ReceiverId
,RM.ReceiverDateas [Receiver Date]
,VM.VendorName as [Vendor Name]
,VM.VendorID
FROM Receiver RM
LEFT OUTER JOIN VendorMaster VM on VM.VendorID = RM.VendorId
WHERE ['+ #ColumnName + '] LIKE
CASE WHEN ' + #Filter+ ' = 0 THEN ''%' + #Value + '%'''+
' WHEN ' + #Filter + ' = 1 THEN '''+ #Value + '%'''+
' WHEN ' + #Filter + ' = 2 THEN ''%' + #Value +''' END
AND VM.IsActive = 1
AND RM.VendorID = CASE WHEN ' + CONVERT(VARCHAR, #VendorID) + ' = ''-1'' THEN RM.VendorID
ELSE '+ CONVERT(VARCHAR, #VendorID) +' END
AND (RM.ReceiverDate BETWEEN ' + CHAR(39) + CONVERT(VARCHAR(23), #FromDate, 126) + CHAR(39) +' AND ' + CHAR(39) + CONVERT(VARCHAR(23), #ToDate, 126) + CHAR(39) +')
ORDER BY RM.ReceiverDate '
My question is: how to add DISTINCT to the ReceiverId ?
I get this error:
Incorrect syntax near the keyword 'DISTINCT'.
in the C# code behind
with cte
as
(
Select ROW_NUMBER() OVER (PARTITION BY ReceiverId ORDER BY ReceiverId ) AS dupCount, *
from(
SELECT ROW_NUMBER() OVER (ORDER BY ReceivedDate) AS [S. No.]
,RM.ReceiverId
,RM.ReceiverName'
,VM.VendorName
, XYZ columns .....
From Receiver RM
LEFT OUTER JOIN VendorMaster VM on VM.VendorID = RM.VendorId
) tab
)
select S. No.
,ReceiverId
,ReceiverName
,VendorName
, XYZ columns
from cte
where dupcount=1;
try using cte.
DECLARE #ReadData NVARCHAR(MAX);
set #ReadData = 'SELECT *
,ROW_NUMBER() OVER (ORDER BY ReceivedDate) AS [S. No.]
FROM (SELECT DISTINCT ReceiverId,
ReceivedDate
,ReceiverName
, XYZ columns .....
From Receiver .........
INNER JOIN .......)'
You can't use the row_number and distinct on same level.

SQL Server 2008 R2: Invalid column name in PIVOT query

I have a dynamic pivot query and I want to pivot on businessaccountnumber which I know exist in the transaction_table but it keeps returning that "Invalid column name 'bizi'."- for line 1.
DECLARE #Output nvarchar(max) = N''
DECLARE #PivotList varchar(max)
SELECT
#PivotList = COALESCE(#PivotList + ', ', N'') + N'[' + bizid + N']'
FROM (SELECT DISTINCT
BusinessAccountNumber [bizid]
FROM transaction_table
WHERE postingdate BETWEEN '1/01/2015' AND '2/01/2015'
) AS CustProds;
SET #Output = 'SELECT [bizName],[bizi]
, ' + #PivotList + '
FROM ( select businessname as [bizName],businessaccountnumber as [bizi],
sum((Transactionamount*(-1))) as [Transactionamount]
FROM transaction_table
WHERE postingdate between ''1/01/2015'' and ''2/01/2015''
GROUP BY businessaccountnumber,businessname) as P
PIVOT ( SUM(Transactionamount) FOR P.bizi IN (' + #PivotList + ') ) AS PVT'
EXEC sp_executesql #Output;
EDIT: Thanks to Backs for pointing out my error but now I have a new error.
the output I am looking for is:
Date | bizid12| bizid13| bizid14...
01/01/2015| $1 | $3 | $56
01/02/2015| $12 | $34 | $3
.....
DECLARE #Output nvarchar(max) = N''
DECLARE #PivotList varchar(max)
SELECT
#PivotList = COALESCE(#PivotList + ', ', N'') + N'[' + bizid + N']'
FROM (SELECT DISTINCT
BusinessAccountNumber [bizid]
FROM transaction_table
WHERE postingdate BETWEEN '1/01/2015' AND '2/01/2015'
) AS CustProds;
SET #Output = 'SELECT [sp_date]
, ' + #PivotList + '
FROM ( select Convert(varchar,postingdate,101) as [sp_date]
,businessaccountnumber as [bizi],
sum((Transactionamount*(-1))) as [Transactionamount]
FROM transaction_table
WHERE postingdate between ''1/01/2015'' and ''2/01/2015''
GROUP BY businessaccountnumber) as P
PIVOT ( SUM(Transactionamount) FOR P.bizi IN (' + #PivotList + ') ) AS PVT'
EXEC sp_executesql #Output;
Error now says:
Msg 8180, Level 16, State 1, Line 1
Statement(s) could not be prepared.
Msg 102, Level 15, State 1, Line 1
Incorrect syntax near 'Qry12090'.
Msg 1056, Level 15, State 1, Line 1
The number of elements in the select list exceeds the maximum allowed number of 4096 elements.
You can't select bizi in query SELECT [bizName],[bizi] using it in PIVOT FOR P.bizi IN. Remove [bizi] from select statement

How to write the proper syntax for this line of code in my SQL dynamic Pivot Query?

I have a dynamic pivot query running on SQL Server 2014. This is my original query and it runs fine:
DECLARE #sql NVARCHAR(max),
#cols VARCHAR(max)
SET #cols = (SELECT DISTINCT a.FOC_TRANSACTIONCODE + ','
FROM P5FOLIOCHARGE a
LEFT JOIN P5FOLIOHEADER b
ON a.FOC_ACCOUNT = b.FOH_ACCOUNT
WHERE b.FOH_PMSCONFIRMATIONNUMBER = '39576189-1'
AND FOC_NETAMOUNT NOT LIKE '-%'
FOR xml path(''))
SELECT #cols = LEFT(#cols, Len(#cols) - 1)
SET #sql = 'SELECT *
FROM (SELECT b.FOH_PMSCONFIRMATIONNUMBER,
a.FOC_ACCOUNT,
a.FOC_PROPERTY,
a.FOC_DATE,
a.FOC_TRANSACTIONCODE,
CASE WHEN a.FOC_NETAMOUNT > 0 THEN a.FOC_NETAMOUNT ELSE 0 END AS FOC_NETAMOUNT
FROM P5FOLIOCHARGE a
LEFT JOIN P5FOLIOHEADER b ON a.FOC_ACCOUNT = b.FOH_ACCOUNT
where b.FOH_PMSCONFIRMATIONNUMBER = ''39576189-1''
AND FOC_NETAMOUNT NOT LIKE ''-%'')a
PIVOT (Sum(FOC_NETAMOUNT)
FOR FOC_TRANSACTIONCODE IN (' + #cols + ')) pv '
EXEC Sp_executesql #sql
I have now modified it a bit but I am running into a syntax error with the following line of code that I have added:
WHERE datename(m,FOC_DATE) + ' ' + cast(datepart(yyyy,FOC_DATE) as varchar) = 'FEBRUARY 2015'
The query now looks as this:
DECLARE #sql NVARCHAR(max),
#cols VARCHAR(max)
SET #cols = (SELECT DISTINCT a.FOC_TRANSACTIONCODE + ','
FROM P5FOLIOCHARGE a
LEFT JOIN P5FOLIOHEADER b
ON a.FOC_ACCOUNT = b.FOH_ACCOUNT
WHERE datename(m,FOC_DATE) + ' ' + cast(datepart(yyyy,FOC_DATE) as varchar) = 'FEBRUARY 2015'
AND FOC_PROPERTY = 'ZIL'
AND FOC_NETAMOUNT NOT LIKE '-%'
FOR xml path(''))
SELECT #cols = LEFT(#cols, Len(#cols) - 1)
SET #sql = 'SELECT *
FROM (SELECT b.FOH_PMSCONFIRMATIONNUMBER,
a.FOC_ACCOUNT,
a.FOC_date,
a.FOC_PROPERTY,
a.FOC_TRANSACTIONCODE,
CASE WHEN a.FOC_NETAMOUNT > 0 THEN a.FOC_NETAMOUNT ELSE 0 END AS FOC_NETAMOUNT
FROM P5FOLIOCHARGE a
LEFT JOIN P5FOLIOHEADER b ON a.FOC_ACCOUNT = b.FOH_ACCOUNT
WHERE datename(m,FOC_DATE) + ' ' + cast(datepart(yyyy,FOC_DATE) as varchar) = ''FEBRUARY 2015''
AND FOC_PROPERTY = 'ZIL'
AND FOC_NETAMOUNT NOT LIKE ''-%'')a
PIVOT (Sum(FOC_NETAMOUNT)
FOR FOC_TRANSACTIONCODE IN (' + #cols + ')) pv '
EXEC Sp_executesql #sql
I am having a syntax error (on the code I mentioned above) where it appears the second time in the query (that is, after the SET # sql=....)
I have tried several combinations of using the ' sign but it still fails. I guess it must be a simple coding syntax error but it just isn't working for me!
I'm Not sure but please check this
WHERE datename(m,FOC_DATE) + ' ' + cast(datepart(yyyy,FOC_DATE) as varchar) = ''FEBRUARY 2015'' it should be WHERE datename(m,FOC_DATE) + '' '' + cast(datepart(yyyy,FOC_DATE) as varchar) = ''FEBRUARY 2015''
AND FOC_PROPERTY = 'ZIL' it should be AND FOC_PROPERTY = ''ZIL''

Resources