Performance issue with stored procedure [closed] - sql

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 7 years ago.
Improve this question
I have a stored procedure that uses the while loop temp table and cursor by which I gets the aging balance of customer, however my SP is working fine but I have some performance concerns as its take 15 sec to produce results from a small chunk of data. I am looking for a more efficient way to do this.
Thanks in advance.
Here is my stored procedure.
CREATE TABLE #Customer_Temp (
AccountCode varchar(50),
AccountTitle varchar(50),
CurrentBalance int,
FirstBalance int,
SecondBalance int,
ThirdBalance int,
FourthBalance int,
FifthBalance int,
SixthBalance int,
SeventhBalance int,
EighthBalance int,
OpeningBalance int
)
INSERT INTO #customer_temp (AccountCode, AccountTitle, OpeningBalance)
SELECT
Customer.AccountCode,
Customer.Name,
COA.OpeningBalance
FROM Customers AS Customer
INNER JOIN ChartOfAccount AS COA
ON COA.CompanyId = #Companyid
AND COA.BusinessUnitId = #BusinessUnitId
AND COA.ChartAccount = Customer.AccountCode
--Create Table And Duplicate Customers Data In it ENDED
DECLARE #DrAmount AS int
DECLARE #CrAmount AS int
DECLARE #Balance AS int
DECLARE #FBalance AS int
DECLARE #SBalance AS int
DECLARE #TBalance AS int
DECLARE #FoBalance AS int
DECLARE #FIBalance AS int
DECLARE #SIBalance AS int
DECLARE #SEBalance AS int
DECLARE #EBalance AS int
DECLARE #FSDate AS date
DECLARE #FLDate AS date
DECLARE #SSDate AS date
DECLARE #SLDate AS date
DECLARE #TSDate AS date
DECLARE #TLDate AS date
DECLARE #FOSDate AS date
DECLARE #FOLDate AS date
DECLARE #FISDate AS date
DECLARE #FILDate AS date
DECLARE #SISDate AS date
DECLARE #SILDate AS date
DECLARE #SESDate AS date
DECLARE #SELDate AS date
DECLARE #ESDate AS date
SET #FSDate = DATEADD(DAY, -1, #StartDate)
SET #FLDate = DATEADD(DAY, -6, #FSDate)
SET #SSDate = DATEADD(DAY, -1, #FLDate)
SET #SLDate = DATEADD(DAY, -6, #SSDate)
SET #TSDate = DATEADD(DAY, -1, #SLDate)
SET #TLDate = DATEADD(DAY, -14, #TSDate)
SET #FOSDate = DATEADD(DAY, -1, #TLDate)
SET #FOLDate = DATEADD(DAY, -14, #FOSDate)
SET #FISDate = DATEADD(DAY, -1, #FOLDate)
SET #FILDate = DATEADD(DAY, -14, #FISDate)
SET #SISDate = DATEADD(DAY, -1, #FILDate)
SET #SILDate = DATEADD(DAY, -29, #SISDate)
SET #SESDate = DATEADD(DAY, -1, #SILDate)
SET #SELDate = DATEADD(DAY, -89, #SESDate)
SET #ESDate = DATEADD(DAY, -1, #SELDate)
DECLARE #TempCCode AS varchar(50)
DECLARE #TempOBalance AS float
DECLARE CustomerCursor CURSOR FOR
SELECT
AccountCode,
OpeningBalance
FROM #Customer_Temp
OPEN CustomerCursor
FETCH NEXT FROM CustomerCursor INTO #TempCCode, #TempOBalance
WHILE ##FETCH_STATUS = 0
BEGIN
EXEC #FBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FSDate,
#FLDate,
#Fyear
EXEC #SBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SSDate,
#SLDate,
#Fyear
EXEC #TBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#TSDate,
#TLDate,
#Fyear
EXEC #FoBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FOSDate,
#FOLDate,
#Fyear
EXEC #FIBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#FISDate,
#FILDate,
#Fyear
EXEC #SIBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SISDate,
#SILDate,
#Fyear
PRINT #SESDate
PRINT #SELDate
EXEC #SEBalance =
GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#SESDate,
#SELDate,
#Fyear
EXEC #EBalance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#ESDate,
#EndDate,
#Fyear
EXEC #Balance = GetBalanceOfAgingOnDate #BusinessUnitId,
#Companyid,
#TempCCode,
#StartDate,
#EndDate,
#Fyear
UPDATE #Customer_Temp
SET CurrentBalance = (#Balance + #TempOBalance),
FirstBalance = #FBalance,
SecondBalance = #SBalance,
ThirdBalance = #TBalance,
FourthBalance = #FoBalance,
FifthBalance = #FIBalance,
SixthBalance = #SIBalance,
SeventhBalance = #SEBalance,
EighthBalance = #EBalance
WHERE AccountCode = #TempCCode
FETCH NEXT FROM CustomerCursor INTO #TempCCode, #TempOBalance
END
CLOSE CustomerCursor
DEALLOCATE CustomerCursor
AND here is the called store procedure in cursor
CREATE PROCEDURE [dbo].[GetBalanceOfAgingOnDate]
#BusinessUnitId int,
#Companyid int,
#ChartAccount as varchar (50),
#StartDate as DateTime,
#EndDate as DateTime,
#Fyear as varchar(50)
AS BEGIN
Declare #DrAmount as int
Declare #CrAmount as int
Declare #Balance as int
set #DrAmount=(select sum(Dr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND AM.FYear = #Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=#ChartAccount AND
AC.CreatedOn Between #EndDate AND #StartDate);
set #CrAmount=(select sum(Cr_Amount) from AccountVocherMaster AS AM ,
AccountVocherChild AS AC Where AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND AM.FYear = #Fyear AND
AM.VocherId = AC.VocherId AND AC.AccountCode=#ChartAccount AND
AC.CreatedOn Between #EndDate AND #StartDate);
set #Balance = #DrAmount - #CrAmount ;
return ISNULL(#Balance,0)
END

make cursor a local variable DECLARE #CustomerCursor CURSOR, ensure it is not dynamic and does not reflect updates to cursor's source tables SET #CustomerCursor = CURSOR FAST_FORWARD FOR, in the end update by current cursor position, avoid additional search UPDATE #Customer_Temp SET ... WHERE CURRENT OF #CustomerCursor
obtain aggregates of different columns for similar conditions by a single select select #DrAmount = sum(Dr_Amount), #CrAmount = sum(Cr_Amount)
and more of it: select #Balance = sum(Dr_Amount) - sum(Cr_Amount)
avoid ancient-style joining by comma, write inner or outer joins, put joining conditions into ON clause, put filtering into WHERE clause
avoid thinking of SQL as a regular programming language like PHP or Pascal; it is result-set oriented; try making INLINE TABLE FUNCTION instead of procedure (GetBalanceOfAgingOnDate) - this will make you able to join to that from your queries; tip: do not make it scalar-valued or table-valued function. Look at your aggregation sp and how it is used. For each row (company) you call that sp again and again, and aggregate some values inside it. Why not to GROUP BY company and BusinessUnitID, run a single select from AccountVocherMaster and join it to your #Customer_Temp? Why not to aggregate summary for different periods by a single query? Look again: you have a list of companies, an aggregation query that provides some summarized values grouped by companies... why do you still have a cursor at all? it's a single query job
if you have lots of data and filtering by dates is the only way that makes it run fast - make not a single query, make 10 queries. this anyway will be much better than 10*2*[N companies] Actually period required is well determined - max range is [#StartDate-180, #StartDate] - and it looks like a single query is a good idea again. In some cases, if your data is very big, cursor and filtering by a scalar values may still be a good change to improve performance, thus you may still want to filter by a single CompanyID - ok, but the data you aggregate is still located in fixed date range in the same two tables - AccountVocherMaster and AccountVocherChild; loop through companies, run single aggregation query inside the cursor
there is absolutely nothing smart in your GetBalanceOfAgingOnDate's sources - don't know why you keep it as a separate module
there must be a transaction around it

Your problem is that you do not think SQL and try to be smart - you write procedural code, which SQL Server has to execute one by one INSTEAD of working in set and letting the query optimizer figure out how to do that most efficient.
Cursors and procedures are generally slow elements. You are better to forumulate this in as few atomic SQL statements as possible, even if the statements are a page or two long. Then the query optimizer can figure out how to achieve this result most efficient.
In your case, the second SP gets called repeatedly in the cursor - there are likely ways to achieve this better. In one or a lot less calls.

Hopefully this can start you down the path. There is a lot in your question, so I may not (a) understand everything here and (b) address every part, but hopefully you can take it from here. I don't see the need for any procedures or loops. Give this a try, I've commented some for context:
/* Construct a temp table to store all balance dates (and respective names) */
CREATE TABLE #BalanceDates (BalanceName VARCHAR(20), StartDate DATETIME, EndDate DATETIME);
INSERT INTO BalanceDates VALUES ('FirstBalance',DATEADD(DAY,-1,#StartDate),DATEADD(DAY,-6,#StartDate));
-- And so on with remaining inserts...
/* Create a denormalized table of all balances */
SELECT
[FirstBalance],
[SecondBalance],
...
INTO
#Balances
FROM
(
SELECT
BD.BalanceName,
ISNULL(SUM(Dr_Amount) - SUM(Cr_Amount),0) AS BalanceAmount
FROM
#BalanceDates BD
LEFT JOIN
AccountVocherChild AC
ON (AC.CreatedOn BETWEEN BD.StartDate AND BD.EndDate)
LEFT JOIN
AccountVocherMaster AM
ON (AM.VocherId = AC.VocherId)
WHERE
AM.CompanyId = #Companyid AND
AM.BusinessUnitId = #BusinessUnitId AND
AM.FYear = #Fyear AND
AC.AccountCode = #ChartAccount
GROUP BY
BD.BalanceName
) data
PIVOT
(
AVG(BalanceAmount)
FOR BalanceName IN ([FirstBalance],[SecondBalance],...)
) pvt;
/* Update the table accordingly */
UPDATE tgt
SET
FirstBalance = src.FirstBalance,
SecondBalance = src.SecondBalance,
...
FROM #Customer_Temp tgt
JOIN #Balances src
ON (1 = 1);

Related

How to improve while loop insert performance in sql server?

Here is my SQL Query. It's insert almost 6500+ row from temp table. But its takes 15+ mins! . How can i improve this ? Thanks
ALTER proc [dbo].[Process_bill]
#userid varchar(10),
#remark nvarchar(500),
#tdate date ,
#pdate date
as
BEGIN
IF OBJECT_ID('tempdb.dbo..#temptbl_bill', 'U') IS NOT NULL
DROP TABLE #temptbl_bill;
CREATE TABLE #temptbl_bill (
RowID int IDENTITY(1, 1),
------------
)
// instert into temp table
DECLARE #NumberRecords int, #RowCounter int
DECLARE #batch INT
SET #batch = 300
SET #NumberRecords = (SELECT COUNT(*) FROM #temptbl_bill)
SET #RowCounter = 1
SET NOCOUNT ON
BEGIN TRANSACTION
WHILE #RowCounter <= #NumberRecords
BEGIN
declare #clid int
declare #hlid int
declare #holdinNo nvarchar(150)
declare #clientid nvarchar(100)
declare #clientName nvarchar(50)
declare #floor int
declare #radius nvarchar(50)
declare #bill money
declare #others money
declare #frate int
declare #due money
DECLARE #fine money
DECLARE #rebate money
IF #RowCounter > 0 AND ((#RowCounter % #batch = 0) OR (#RowCounter = #NumberRecords))
BEGIN
COMMIT TRANSACTION
PRINT CONCAT('Transaction #', CEILING(#RowCounter/ CAST(#batch AS FLOAT)), ' committed (', #RowCounter,' rows)');
BEGIN TRANSACTION
END;
// multiple select
// insert to destination table
Print 'RowCount -' +cast(#RowCounter as varchar(20)) + 'batch -' + cast(#batch as varchar(20))
SET #RowCounter = #RowCounter + 1;
END
COMMIT TRANSACTION
PRINT CONCAT('Transaction #', CEILING(#RowCounter/ CAST(#batch AS FLOAT)), ' committed (',
#RowCounter,' rows)');
SET NOCOUNT OFF
DROP TABLE #temptbl_bill
END
GO
As has been said in comments, the loop is completely unnecessary. The way to improve the performance of any loop is to remove it completely. Loops are a last resort in SQL.
As far as I can tell your insert can be written with a single statement:
INSERT tbl_bill(clid, hlid, holdingNo,ClientID, ClientName, billno, date_month, unit, others, fine, due, bill, rebate, remark, payment_date, inserted_by, inserted_date)
SELECT clid = c.id,
hlid = h.id,
h.holdinNo ,
c.cliendID,
clientName = CAST(c.clientName AS NVARCHAR(50)),
BillNo = CONCAT(h.holdinNo, MONTH(#tdate), YEAR(#tdate)),
date_month = #tDate,
unit = 0,
others = CASE WHEN h.hfloor = 0 THEN rs.frate * (h.hfloor - 1) ELSE 0 END,
fine = bs.FineRate * b.Due / 100,
due = b.Due,
bill = #bill, -- This is declared but never assigned
rebate = bs.rebate,
remark = #remark,
payment_date = #pdate,
inserted_by = #userid,
inserted_date = GETDATE()
FROM ( SELECT id, clientdID, ClientName
FROM tbl_client
WHERE status = 1
) AS c
INNER JOIN
( SELECT id, holdinNo, [floor], connect_radius
FROM tx_holding
WHERE status = 1
AND connect_radius <> '0'
AND type = 'Residential'
) AS h
ON c.id = h.clid
LEFT JOIN tbl_radius_setting AS rs
ON rs.radius= CONVERT(real,h.connect_radius)
AND rs.status = 1
AND rs.type = 'Non-Govt.'
LEFT JOIN tbl_bill_setting AS bs
ON bs.Status = 1
LEFT JOIN
( SELECT hlid,
SUM(netbill) AS Due
FROM tbl_bill AS b
WHERE date_month < #tdate
AND (b.ispay = 0 OR b.ispay IS NULL)
GROUP BY hlid
) AS b
ON b.hlid = h.id
WHERE NOT EXISTS
( SELECT 1
FROM tbl_bill AS tb
WHERE EOMONTH(#tdate) = EOMONTH(date_month)
AND tb.holdingNo = h.holdinNo
AND (tb.update_by IS NOT NULL OR tb.ispay=1)
);
Please take this with a pinch of salt, it was quite hard work trying to piece together the logic, so it may need some minor tweaks and corrections
As well as adapting this to work as a single statement, I have made a number of modifications to your existing code:
Swapped NOT IN for NOT EXISTS to avoid any issues with null records. If holdingNo is nullable, they are equivalent, if holdingNo is nullable, NOT EXISTS is safer - Not Exists Vs Not IN
The join syntax you are using was replaced 27 years ago, so I switched from ANSI-89 join syntax to ANSI-92. - Bad habits to kick : using old-style JOINs
Changed predicates of YEAR(date_month) = YEAR(#tDate) AND MONTH(date_month) = MONTH(#tDate) to become EOMONTH(#tdate) = EOMONTH(date_month). These are syntactically the same, but EOMONTH is Sargable, whereas MONTH and YEAR are not.
Then a few further links/suggestions that are directly related to changes I have made
Although I removed the while lopp, don't fall into the trap of thinking this is better than a cursor. A properly declared cursor will out perform a while loop like yours - Bad Habits to Kick : Thinking a WHILE loop isn't a CURSOR
The general consensus is that prefixing object names is not a good idea. It should either be obvious from the context if an object is a table/view or function/procedure, or it should be irrelevant - i.e. There is no need to distinguish between a table or a view, and in fact, we may wish to change from one to the other, so having the prefix makes things worse, not better.
The average ratio of time spent reading code to time spent writing code is around 10:1 - It is therefore worth the effort to format your code when you are writing it so that it is easy to read. This is hugely subjective with SQL, and I would not recommend any particular conventions, but I cannot believe for a second you find your original code free flowing and easy to read. It took me about 10 minutes just unravel the first insert statement.
EDIT
The above is not correct, EOMONTH() is not sargable, so does not perform any better than YEAR(x) = YEAR(y) AND MONTH(x) = MONTH(y), although it is still a bit simpler. If you want a truly sargable predicate you will need to create a start and end date using #tdate, so you can use:
DATEADD(MONTH, DATEDIFF(MONTH, '19000101', #tdate), '19000101')
to get the first day of the month for #tdate, then almost the same forumla, but add months to 1st February 1900 rather than 1st January to get the start of the next month:
DATEADD(MONTH, DATEDIFF(MONTH, '19000201', #tdate), '19000201')
So the following:
DECLARE #Tdate DATE = '2019-10-11';
SELECT DATEADD(MONTH, DATEDIFF(MONTH, '19000101', #tdate), '19000101'),
DATEADD(MONTH, DATEDIFF(MONTH, '19000201', #tdate), '19000201');
Will return 1st October and 1st November respectively. Putting this back in your original query would give:
WHERE NOT EXISTS
( SELECT 1
FROM tbl_bill AS tb
WHERE date_month >= DATEADD(MONTH, DATEDIFF(MONTH, '19000101', #tdate), '19000101'),
AND date_month < DATEADD(MONTH, DATEDIFF(MONTH, '19000201', #tdate), '19000201')
AND tb.holdingNo = h.holdinNo
AND (tb.update_by IS NOT NULL OR tb.ispay=1)
);

SQL query loops twice through each row?

When I trigger my stored procedure from a web app, it loops twice and creates two identical entries of the same row. I cannot work out why :/
The query is supposed to INSERT (re-schedule) all submitted rows. It uses a cursor to go through each row and SELECT, then INSERT, the correct data from/for each row.
Here is my SQL:
CREATE PROCEDURE [cil].[executeCIL_updateComplDate_And_ReSchedule]
#equipID INT,
#date DATE,
#ip VARCHAR(15)
AS
/* add completion date */
UPDATE cil.schedule
SET completionDate = CAST(GETUTCDATE() AS SMALLDATETIME),
complIP = #ip
WHERE schedule.id IN (SELECT schedule.id
FROM cil.schedule
LEFT JOIN cil.task ON cil.schedule.taskFK = cil.task.id
--WHERE CAST(scheduledDate AS DATE)<=CAST(GetDate() AS DATE)
WHERE CAST(scheduledDate as DATE) = #date
AND completionDate IS NULL
AND result IS NOT NULL
AND equipFK = #equipID);
/* reschedule tasks */
DECLARE #nextTaskID AS INT;
DECLARE #nextScheduledDate AS DATETIME2(6);
DECLARE #nextRotaCycle AS INT;
DECLARE db_cursor CURSOR FOR
SELECT taskFK, scheduledDate, rotaCycle
FROM cil.schedule
LEFT JOIN cil.task ON cil.schedule.taskFK = cil.task.id
WHERE completionDate = CAST(GETUTCDATE() AS SMALLDATETIME)
AND equipFK = #equipID;
OPEN db_cursor;
FETCH NEXT FROM db_cursor INTO #nextTaskID, #nextScheduledDate, #nextRotaCycle;
WHILE ##FETCH_STATUS = 0
BEGIN
--Do stuff with scalar values
INSERT INTO cil.schedule (taskFK, scheduledDate, rotaCycle)
VALUES (#nextTaskID,
DATEADD(dd, #nextRotaCycle, #nextScheduledDate),
#nextRotaCycle)
FETCH NEXT FROM db_cursor INTO #nextTaskID, #nextScheduledDate,
#nextRotaCycle;
END;
CLOSE db_cursor;
DEALLOCATE db_cursor;
GO
It seems that you have duplicates caused by a join of the query of the cursor
If you run this query externally, in SSMS, will it produce only the one row?
SELECT taskFK, scheduledDate, rotaCycle
FROM cil.schedule
LEFT JOIN cil.task ON cil.schedule.taskFK=cil.task.id
WHERE completionDate=CAST(GETUTCDATE() AS SMALLDATETIME)
AND equipFK=#equipID ;
and doubles comes from a table task.
If this table is not in use, consider to remove it

How to pass dynamic View name in SQL stored procedure without using a dynamic query?

Here is my stored procedure below. I am concatenating #CultureCode paramter along with view name which is [_0002HR_EmployeeNames_en-US_View]. The part en-US will be passed through a parameter named as #CultureCode. Is there any way to do so because i have requirement not to use dynamic query. Thank you.
CREATE PROCEDURE [dbo].[_001HR_Report_Loans] (#Parameters VARCHAR(max))
AS
DECLARE #ReportOption VARCHAR(5) SET #ReportOption = [dbo].DB_Split(#Parameters, 1)
DECLARE #CultureCode VARCHAR(10) SET #CultureCode = [dbo].DB_Split(#Parameters, 2)
DECLARE #ShowItems VARCHAR(5) SET #ShowItems = [dbo].DB_Split(#Parameters, 3)
DECLARE #StartDate NVARCHAR(8) SET #StartDate = [dbo].DB_Split(#Parameters, 4)
DECLARE #EndDate NVARCHAR(8) SET #EndDate = [dbo].DB_Split(#Parameters, 5)
DECLARE #EmployeeCode NVARCHAR(30) SET #EmployeeCode = [dbo].DB_Split(#Parameters, 6)
DECLARE #BranchCode NVARCHAR(30) SET #BranchCode = [dbo].DB_Split(#Parameters, 7)
--IF #StartDate = ''
-- SET #StartDate = NULL
SELECT HR.*, EN.[Name] AS EmployeeName
FROM [0002HR_EmployeeLoans] HR
LEFT JOIN [_0002HR_EmployeeNames_ + '#CultureCode' +_View] EN ON HR.EmployeeCode = EN.EmployeeCode
LEFT JOIN [_0002HR_EmployeePackagesView] EP ON EP.EmployeeCode = HR.EmployeeCode
WHERE
(HR.EmployeeCode = #EmployeeCode OR #EmployeeCode IS NULL)
AND
(EP.BranchCode = #BranchCode OR #BranchCode IS NULL)
AND
(HR.Date BETWEEN #StartDate AND #EndDate OR #StartDate IS NULL AND #EndDate IS NULL)
AND
(HR.Date >= #StartDate OR #StartDate IS NULL)
AND
(HR.Date <= #EndDate OR #EndDate IS NULL)
This is not possible in T-SQL so far. Things like TOP clauses, table or column names can not be parameterized.
One way would be to create a union over all possible tables/views, add a new column that matches the table/view name and filter that.
Like this:
SELECT * FROM
(
SELECT 'Table1' as TableName, t1.* FROM Table1 t1 WHERE ...
UNION ALL
SELECT 'Table2' as TableName, t2.* FROM Table2 t2 WHERE ...
) tmp
WHERE TableName = #tableName
Another (and possibly the most "clean" way) would be to only have one single table and make the culture a column in that table, so you only need to pass the correct culture string to filter over that column.
So you have a view per language. They are getting the data from the tables for their particular language. But now you want to write a procedure that is not language-specific.
The solution seems simple: Don't use the language views, but access the tables directly instead. (Or build an all-languages view which you query with where language = #language.)

ssrs Ignoring variable which is not declared

This is my part of the query which i am using in the Dataset in SSRS2008
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime = (SELECT TOP 1 StartDate FROM UserManagerDates WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #StartDate = #NewStartDate;
END
Question:
I was copying my query into dataset from ssms and when i hit refresh in dataset i only get prompted for #a and #b in define query parameters. Actually i wasn't even declaring #startdate so i was expecting #startdate variable in define query parameters tab. What changes should i make to to get prompted for #startdate along with the other two variables?
You are setting the #startdate parameter, it is supposed to be populated by SSRS instead of your query, that could be the reason you are not being prompted.
I think you want to use #startdate to populate #NewStartDate, if so try this:
DECLARE #SERVER VARCHAR(20) = null;
Declare #curDATEFIRST as Integer = ##DATEFIRST;
SET DATEFIRST 1;
IF #a=0 AND #b>1
BEGIN
DECLARE #NewStartDate DateTime =
(SELECT TOP 1 StartDate FROM UserManagerDates
WHERE EmployeeID=#b ORDER BY StartDate DESC);
IF #NewStartDate>#StartDate SET #NewStartDate = #startdate;
END

Select statement with a Split function

I am using a select split function in stored procedure to pass a multiple selection IDS like below .
SELECT Status AS ClientInbox, COUNT(submitTime) AS CountStatus
FROM dbo.ClientInbox with (nolock) join debtor with (nolock) on ClientInbox.debtorid = debtor.id
WHERE (submitTime >= #fromDate and submittime <= #toDate)
and debtor.clientid IN (SELECT ID FROM [dbo].[split_IDs] (#clientid,','))
GROUP BY Status
Where [dbo].[split_IDs] is a function. My problem is while testing, when i replcae the variable #clientid with a set of setrings like ('1,2,3,4,5'), the query returns the required records. But when i run the procedure from VS, it does not return the exact records. I try to figure out what the problem is by executing the procedure in the SQL server as below
USE [Volare_2005]
GO
DECLARE #return_value int
DECLARE #fromDate datetime
DECLARE #toDate datetime
EXEC #return_value = [dbo].[GetSMSReportDate]
#fromDate = '2000-04-06T12:23:45',
#toDate = '2013-10-22T21:10:12',
#option = 0 ,
#collectorid = 0,
#supervisorid = 0,
#clientid = N'95,1'
--SELECT 'Return Value' = #return_value
GO
It fails the return the records as well. However it works fine when i run the query by replcaing the variable #clientid in the procedure. I am not sure were i go wrong. Please any help would be appreciate