Pivoting table gives error : Must declare the scalar variable #start1 - sql

Error :
Must declare the scalar variable "#start1".
Here is my query, I have two functions and am trying to pivot the data. The first function dbo.fxnExample accepts parameters is good but the second function dbo.fxnExample2 does not accept the parameters value, it pass 0 as the value.
ALTER proc [dbo].[SpTimesheetCrossTableFormat]
#start NVARCHAR(20),
#end NVARCHAR(20)
AS
BEGIN
DECLARE #DynamicPivotQuery AS NVARCHAR(MAX),
#PivotColumnNames AS NVARCHAR(MAX),
#PivotSelectColumnNames AS NVARCHAR(MAX)
DECLARE #start1 as nvarchar(20)=#start
DECLARE #start2 as nvarchar(20)=#end
--Get DISTINCT values of the PIVOT Column
SELECT #PivotColumnNames= convert(NVARCHAR(max),(ISNULL(#PivotColumnNames + ',','')))
+ CONVERT(NVARCHAR(max),(QUOTENAME(project_name)))
FROM (SELECT DISTINCT project_name FROM dbo.fxnExample(#start,#end)) AS project_name
--Get DISTINCT values of the PIVOT Column with isnull
SELECT #PivotSelectColumnNames
= ISNULL(#PivotSelectColumnNames + ',','')
+ 'ISNULL(' + QUOTENAME(project_name) + ', 0) AS '
+ QUOTENAME(project_name)
FROM (SELECT DISTINCT project_name FROM dbo.fxnExample(#start,#end)) AS project_name
--Prepare the PIVOT query using the dynamic
SET #DynamicPivotQuery =
N'SELECT d, user_name, ' + #PivotSelectColumnNames + '
FROM dbo.fxnExample2(#start1,#start2)
PIVOT(SUM(mins)
FOR project_name IN (' + #PivotColumnNames + ')) AS PVTTable'
--Execute the Dynamic Pivot Query
EXEC sp_executesql #DynamicPivotQuery
END
Here is the function :
CREATE FUNCTION [dbo].[fxnExample2] (#StartDate NVARCHAR(20),#EndDate NVARCHAR(20))
RETURNS TABLE
AS
RETURN
(
SELECT user_details.user_name,project_details.name as project_name,
--(ISNULL( DATEDIFF(mi,convert(datetime,punch_in,108), CONVERT(datetime,punch_out,108)),0)) as mins
[hours] as mins ,#StartDate as d
FROM timesheets
JOIN user_details
ON timesheets.user_id=user_details.id
JOIN project_details
ON timesheets.project_id=project_details.id
WHERE CONVERT(date, timesheets.tdate, 103) BETWEEN CONVERT(date, #StartDate, 103) and convert(date, #EndDate, 103)
--where CONVERT(date, tdate, 103) BETWEEN CONVERT(date, '15/08/2019', 103) AND CONVERT(date, '15/08/2019', 103)
)`
fnexample function
`CREATE FUNCTION [dbo].[fxnExample] (#StartDate nvarchar(20),#EndDate nvarchar(20))
RETURNS TABLE
AS
RETURN
(
SELECT user_details.user_name,project_details.name as project_name,
--(ISNULL( DATEDIFF(mi,CONVERT(datetime,punch_in,108), CONVERT(datetime,punch_out,108)),0)) as mins
[hours] as mins
FROM timesheets
JOIN user_details
ON timesheets.user_id=user_details.id
JOIN project_details
ON timesheets.project_id=project_details.id
WHERE CONVERT(date, tdate, 103) BETWEEN CONVERT(date, #StartDate, 103) AND CONVERT(date, #EndDate, 103)
--where CONVERT(date, tdate, 103) BETWEEN CONVERT(date, '05/08/2020', 103) AND CONVERT(date, '05/08/2019', 103)
)

Explanations about your error:
You are trying to execute a dynamic T-SQL statement using sp_executesql. If this statement contains parameters, you need to pass definitions of these parameters and their values to sp_executesql.
In your case, execute your statement in the following way:
EXEC sp_executesql
#DynamicPivotQuery,
N'#start1 as nvarchar(20), #start2 as nvarchar(20)',
#start1,
#start2
Notes:
It's good to check the result from sp_executesql call and optionally print this statement before the execution:
DECLARE #err int
PRINT #DynamicPivotQuery
EXEC #err = sp_executesql
#DynamicPivotQuery,
N'#start1 as nvarchar(20), #start2 as nvarchar(20)',
#start1,
#start2
IF #err = 0 PRINT 'OK' ELSE PRINT 'Error'

Related

dynamic pivot with parameter passed in

I have created this stored procedure that works when hard coded
(in the where clause at #WeekStart and #WeekEnd),
If I try to add parameters to the query #WeekStart and #WeekEnd I get the following error:
Must declare the scalar variable "#WeekStart".
My goal is to do do something like this instead of having to hard code it:
exec dbo.GetTotals #WeekStart='2022-04-11',#WeekEnd='2022-04-25'
The stored procedure:
CREATE PROCEDURE [dbo].[GetTotals]
#WeekStart Date,
#WeekEnd Date
AS
begin
set nocount on;
--get row names
DECLARE
#columns NVARCHAR(MAX) = '',
#sql NVARCHAR(MAX) = '';
-- select the category names
SELECT
#columns+=QUOTENAME(DepartmentName) + ','
FROM
DepartmentTable
ORDER BY
DepartmentName;
--set#colums variable
SET #columns = LEFT(#columns, LEN(#columns) - 1);
-- construct dynamic SQL
SET #sql ='
SELECT * FROM
(
select
JobCode,
DepartmentName,
(COALESCE(MonTime, 0)+COALESCE(TueTime, 0)+COALESCE(WenTime, 0)+COALESCE(ThurTime, 0)+COALESCE(FriTime, 0)
+COALESCE(SatTime, 0)+COALESCE(SunTime, 0)) as total
from TimeSheetTable
INNER JOIN DepartmentTable ON TimeSheetTable.DeptId=DepartmentTable.Id
inner join JobCodeTable on TimeSheetTable.JobId=JobCodeTable.Id
--This Works--
-- Where WeekStartDate Between ''2022-04-11'' and ''2022-04-11'' --
--This is throwing an erro--
Where WeekStartDate Between #WeekStart and #WeekEnd
) t
PIVOT(
sum(total)
FOR DepartmentName IN ('+ #columns +')
)pivot_table
ORDER BY JobCode
'
---- execute the dynamic SQL
EXECUTE sp_executesql #sql;
end
exec sp_executesql #Sql, N' #WeekStart Date, #WeekEnd Date', #WeekStart = #WeekStart, #WeekEnd = #WeekEnd

Must declare the scalar variable pivot sql query

i am generating attendance report by pivot SQL on the basis of data thought thumb impression but the query shows error
Must declare the scalar variable "#abc".
here is my query
DECLARE #cols NVARCHAR(MAX)
DECLARE #abc NVARCHAR(MAX)
set #abc='00:00'
SELECT
top 1 #cols = COALESCE(#cols + ',[' + CONVERT(varchar, DateIn ,106 )
+ ']','[' + CONVERT(varchar, DateIn ,106) + ']' )
FROM DailyAttendanceMaster where
DateIn between '2019-01-01 00:00:00.000' and '2019-01-01 00:00:00.000'
group by DateIn order by DateIn asc
DECLARE #qry NVARCHAR(4000) SET
#qry = 'SELECT * FROM (SELECT Employee_Master.Employee_Name,
case when convert(char(5), TimeIn, 108)= convert(char(5), #abc, 108) then "A"
else "B"
end "TimeIn" ,
DailyAttendanceMaster.DateIn FROM DailyAttendanceMaster inner
join Employee_Master on Employee_Master.essl_EmpID=DailyAttendanceMaster.EMPID)emp
PIVOT (MAX(TimeIn) FOR DateIn IN (' + #cols + ')) AS stat'
EXEC(#qry)
You need to pass variable:
EXEC sp_executesql #qry, N'#abc NVARCHAR(MAX)', #abc

Dynamic query based on datetime parameter

I have a SQL Server database with date representation name like below & each database contains table A (table A having column like id, datetime, value, value1 etc).
Jan2018
Feb2018
Mar2018 and so on..
My search condition is user selected date (eg. from 01-Jan-2018 to 01-Jun-2018) which I am passing to a stored procedure (max range 6 month). I want to generate dynamic query to get data from these database based on datetime passed.
How to achieve this functionality as I found difficult to implement.
Can you try this query
CREATE PROCEDURE Myproc #FromDate DATE,
#ToDate DATE
AS
BEGIN
DECLARE #SQL NVARCHAR(max)='',
#unionall VARCHAR(10)=''
WITH cte
AS (SELECT #FromDate dt,
1 mont
UNION ALL
SELECT Dateadd(month, 1, dt) dt,
mont + 1 mont
FROM cte
WHERE mont < Datediff(month, #FromDate, #ToDate)
)
SELECT #SQL += #unionall + '
select * from ['
+ LEFT (CONVERT(VARCHAR, Datename (month, dt )), 3)
+ CONVERT (VARCHAR, Year (dt))
+ '].[dbo].[tablename]',
#unionall = ' union all '
FROM cte
PRINT #SQL
EXECUTE( #SQL)
END
You should query sys.databases to find a database you need.
Then, as you can only use static declarations of databases, you should create a textual select statement and execute it.
I tried it on my dbs and it worked.
This is my code:
declare #date varchar(20) = '2018'
declare #dbName varchar(20)
declare #sSql varchar(200)
declare #sConditions varchar(20) = ''
Set #dbName = (SELECT name FROM master.sys.databases
where name like '%' + #date + '%')
print #dbName
Select #sSql = 'Select * From ' + #dbName + '.dbo.MyDB '
--+ ' Where ' + #sConditions
Execute (#sSql)
if you need to query all that fit year. do like this:
declare #date varchar(20) = 'a'
SELECT name Into #dbnames
FROM master.sys.databases
where name like '%' + #date + '%'
this brings a table of all sutable dbs. then query each one of them using loop. like cursor
Are you looking for
CREATE PROCEDURE MyProc
#FromDate DATE,
#ToDate DATE,
#Target SysName
AS
BEGIN
DECLARE #SQL NVARCHAR(MAX)= N'SELECT * FROM [' +
#Target +
'] WHERE [Dates] >= #FromDate AND [Dates] <= #ToDate';
EXECUTE sp_executesql #SQL,
N'#FromDate DATE, #ToDate DATE',
#FromDate,
#ToDate;
END
Demo
As I now understand what you are trying to do, you can
CREATE PROCEDURE ProcName
#FromDate DATE,
#ToDate DATE
AS
BEGIN
--Declare a variable to hold the Dynamic SQL
DECLARE #SQL NVARCHAR(MAX) = N'';
--Generate the databases names
WITH CTE AS
(
SELECT #FromDate D,
1 N
UNION ALL
SELECT DATEADD(Month, N, #FromDate),
N + 1
FROM CTE
WHERE N <= DATEDIFF(Month, #FromDate, #ToDate)
)
--Build the SELECT statement
SELECT #SQL = #SQL+
N'SELECT * FROM ['+
CONVERT(VARCHAR(3), D, 100)+
CAST(YEAR(D) AS VARCHAR(4))+
'].dbo.TableName UNION ALL ' --Or UNION as you want
FROM CTE;
--Remove the last UNION ALL
SET #SQL = LEFT(#SQL, LEN(#SQL) - 10); --If UNION then just -6
--Execute the statement
EXECUTE sp_executesql #SQL;
END

Operand type clash: date is incompatible with int While selecting rows

ALTER PROCEDURE [dbo].[Expense_monthly_report] #start_date VARCHAR(100),
#end_date VARCHAR(100)
AS
BEGIN
DECLARE #SQLQuery AS NVARCHAR(max)
DECLARE #PivotColumns AS NVARCHAR(max)
SET nocount ON;
SELECT #PivotColumns = COALESCE(#PivotColumns + ',', '')
+ Quotename( date_of_expp)
FROM (SELECT DISTINCT Month(date_of_exp) AS date_of_expp
FROM [dbo].[tbl_exp_details]
WHERE date_of_exp >= #start_date
AND date_of_exp <= #end_date) AS PivotExample
SET #SQLQuery = N'SELECT p.part_id,' + #PivotColumns
+ ',total_amount FROM (SELECT part_id,month(date_of_exp) as month_of_exp,exp_amount FROM [dbo].[tbl_exp_details]) as tbl PIVOT( sum(exp_amount) FOR month_of_exp IN ('
+ #PivotColumns
+ ')) AS P join (SELECT part_id,sum(exp_amount) as total_amount FROM [dbo].[tbl_exp_details] where date_of_exp>='
+ #start_date + ' and date_of_exp<=' + #end_date
+ ' group by part_id) as la on p.part_id=la.part_id'
EXEC Sp_executesql #SQLQuery
END
I am getting error
date incompatible with int
. Help me to find out the problem.
You have not delimited the date values in the dynamic query.
So
date_of_exp<=' + #end_date
becomes
date_of_exp<= 2017-07-19
which evaluates to this, and int won't implicitly convert to date
date_of_exp <= 1991
The correct way to use Sp_executesql and fix this is:
SET #SQLQuery = N'SELECT p.part_id,' + #PivotColumns
+ ',total_amount FROM (SELECT part_id,month(date_of_exp) as month_of_exp,exp_amount FROM [dbo].[tbl_exp_details]) as tbl PIVOT( sum(exp_amount) FOR month_of_exp IN ('
+ #PivotColumns
+ ')) AS P join (SELECT part_id,sum(exp_amount) as total_amount FROM [dbo].[tbl_exp_details] where date_of_exp>= #start_date and date_of_exp<=#end_date '
+ ' group by part_id) as la on p.part_id=la.part_id'
EXEC Sp_executesql #SQLQuery,
N'#start_date date, #end_date date',
#start_date,
#end_date

Changing manual pivot to dynamic pivot getting aggregate function error

I have a stored procedure for pivoting manually
ALTER procedure [dbo].[performancepivot] (
#startdate datetime,
#enddate datetime
) as begin
set nocount on
declare #date1 nvarchar(100)=convert(varchar, #startdate+'00:00:00.000',120),
#date2 nvarchar(100)= convert(varchar, #enddate+'23:59:59.000',120);
with cte as
dbo.testfunctionstacknew(convert(decimal(10,1),avg(convert(numeric(18,2), datediff(ss, t.Paydate, t.DelDate))))) as Average
from Transaction_tbl as t
left join VType_tbl as v on t.vtid = v.vtid
left join Location_tbl as l on t.Locid = l.Locid
where t.Locid in (select t1.Locid from Transaction_tbl as t1)
and t.dtime between #date1 and #date2
and t.Status = 5
group by v.Vtype, l.LocName, l.Locid)
select c.LocName,
max(case when c.Vtype = 'Normal' then Average end) as Normal,
max(case when c.Vtype = 'Vip' then Average end) as Vip,
max(case when c.Vtype = 'VVip' then Average end) as VVip,
max(case when c.Vtype = 'Pass' then Average end) as Pass,
max(case when c.Vtype = 'Staff' then Average end) as Staff
from cte as c group by c.LocName order by c.LocName
end
while executing this i am getting exact out put..i dont want pivot manually..so i try to write stored procedure 'pivot Dynamically'..
i try to write stored procedure like this:
ALTER procedure [dbo].[ParkingSummary1]
#startdate nvarchar(100), #enddate nvarchar(100) as
begin
declare #date1 nvarchar(100) = convert(varchar, #startdate+' 00:00:00.000', 120)
declare #date2 nvarchar(100) = convert(varchar, #enddate+' 23:59:59.000', 120)
DECLARE #cols AS NVARCHAR(MAX),#query AS NVARCHAR(MAX)
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Vtype) from VType_tbl
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT LocName, ' + #cols + '(
select l.LocName,v.Vtype,[dbo].[testfunctionstacknew](
CONVERT(decimal(10,1), AVG( CONVERT(NUMERIC(18,2),
DATEDIFF(SS,t.Paydate,t.DelDate) ) ))) as Average
from (select l.LocName,Vtype from Transaction_tbl t join
VType_tbl v on t.vtid = v.vtid join dbo.Location_tbl l on
t.locid=l.Locid where dtime between '''+ #date1 +''' and '''+ #date2 +'''
and Status = 5) d pivot ( count(Vtype) for Vtype in (' + #cols + ')) p '
print #query
exec sp_executesql #query;
end
but while executing this stored procedure i am getting error:Column 'Location_tbl.LocName' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.
what is wrong with my second stored procedure..if any one know please help me to find out
You need to execute the command in #query. "print #query" only outputs the command itself. Useful for debugging, so just comment that line out..
insert this under the print command:
exec sp_executesql #query;
more on sp_executesql here:
http://technet.microsoft.com/en-us/library/ms175170(v=sql.105).aspx
EDIT:
The query you generated contains errors. Also it is unnecessary to convert datetimes to varchars to accomplish what you want. This here should fix both (beware, blind coded, #query is only made syntactically correct)
alter procedure [dbo].[ParkingSummary1] (
#startdate datetime
, #enddate datetime )
as
begin
DECLARE #cols AS NVARCHAR(MAX), #query AS NVARCHAR(MAX)
declare #params nvarchar(50) = '#date1 datetime, #date2 datetime';
declare #date1 datetime = dateadd(day, datediff(day, 0, #startdate), 0);
declare #date2 datetime = dateadd(day, datediff(day, 0, #enddate) + 1, 0);
select #cols = STUFF((SELECT distinct ',' + QUOTENAME(Vtype) from VType_tbl
FOR XML PATH(''), TYPE).value('.', 'NVARCHAR(MAX)') ,1,1,'')
set #query = 'SELECT LocName, ' + #cols + '
from
(
select l.LocName, Vtype, [dbo].[testfunctionstacknew](
CONVERT(decimal(10,1), AVG( CONVERT(NUMERIC(18,2),
DATEDIFF(SS,t.Paydate,t.DelDate) ) ))) as Average
from Transaction_tbl t
join VType_tbl v on t.vtid = v.vtid
join dbo.Location_tbl l on t.locid=l.Locid
where dtime >= #date1 and dtime < #date2
and Status = 5
group by l.LocName, VType
) d
pivot ( max(Average) for Vtype in (' + #cols + ')) p '
print #query;
--pass date1 and date2 as datetime parameters, not varchars.
exec sp_executesql #query, #params, #date1, #date2
end
remember to print the variables to debug. Also check the sp_executesql website for an explanation of the #query,#params,#date1,#date2 syntax.