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