UDF not returning the same value as select contained in UDF - sql

I created this UDF
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = (select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate)
return #cnt
END
When I execute the UDF
select dbo.[HasExtendedRetentionSamples] ('ND011811001')
The value 0 is returned, which is incorrect,
When I execute the SQL statement contained in the UDF (replacing #BoxNumber with 'ND011811001')...
select count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
The value 5 is returned, which is correct.
So the big question is WHY????
All the datatype in the joins & case statement are the same.

I would change the function to this, take the count out of the subquery:
CREATE FUNCTION [dbo].[HasExtendedRetentionSamples] (#BoxNumber varchar(20))
RETURNS int
AS
BEGIN
declare #cnt int
set #cnt = 0
select #cnt = count(*)
from tFreezerBoxInfo bi
inner join tFreezerDetails fd on fd.boxTrayId = bi.boxTrayId
inner join tncDrugTestListNew dt on dt.labnumber = fd.labnumber
inner join ExtendedRetentionSites a on dt.number = a.number
where boxnumber = 'ND011811001'
and
case isnull([retention],0)
when 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate
return #cnt
END
try changing your CASE statement to:
case
when isnull([retention],0) = 0 then proposedDestructionDate
else dateadd(dd,abs([retention]),proposedDestructionDate)
end <> proposedDestructionDate

I am embarrassed to say, I have found out why this was happening.....
When I created the table ExtendedRetentionSites, it was created & populated with me as the owner. I realized that and recreated the table with DBO as the owner, populating this table, but never dropping the table with the same name that I owned. I ran an insert statement & it inserted into ExtendedRetentionSites that I owned, but this data never made it to the table that DBO owned.
Soooooo when I ran the select script, it used ExtendedRetentionSites that I owned, that had the new row, that would give me the results I was looking for. When I ran the UDF, it used the table that DBO owned, without the new row thus returning nothing or a zero count.
Thanks to everyone who helped me out with this, I will now pull my head out of my ass & get back to work.
Thanks again to all!!!!

Related

Update Column in table using Select, Inner Join and Case When

I have a table called: Claim, where I've already moved data from another table called Damage. However, today I needed to add a column in Claim called ClaimStatusID. And to give values to ClaimStatusID I need to to it based on another column called DamageApprovedStatusID, which exists in yet another table called DamageErrand. Damage and DamageErrand has relation through a crosstable called DamageErrandCrossDamage. In that crosstable DamageErrandID and DamageID exists. Here, I've commented more information:
-- Claim has column ID which has the same ID as the table Damage
-- DamageErrand has DamageApprovedStatus ID which need to be inserted
-- to ClaimStatusID, where the ID's need to be correct.
-- Table Damage and Table DamageErrand has a cross table:
-- DamageErrandCrossDamage, where both of their ID's are stored
-- Claim.ID should therefore be the same as DamageErrandCrossDamage.DamageID
-- Since Claim.ID has the same ID as Damage.ID
-- IF DamageApprovedStatus = -1, SET ClaimStatusID = 0
-- IF DamageApprovedStatus = 0, SET ClaimStatusID = 4
-- IF DamageApprovedStatus = 1, SET ClaimStatusID = 2
And here's a SQL query I created for selecting and using Case When to give the correct statuses:
SELECT Claim.ID as claimid, DamageErrandID as damageerrandeid,
CASE --
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID,
DamageApprovedStatusID
FROM
DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
WHERE Claim.ID = DamageErrandCrossDamage.DamageID
I do believe this is correct, with the ID's matching and everything. But how can I actually update the table Claim with this? I know insert won't work since I have columns that does not allow null in Claim table. I tried doing something similar to:
--UPDATE Claim
--SET ClaimStatusID =
--(SELECT DamageApprovedStatusID FROM
--DamageErrand
--INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID =
-- DamageErrandCrossDamage.DamageErrandID
--INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID
--WHERE Claim.ID = DamageErrandCrossDamage.DamageID)
But obviously this won't work either. Really thankful for any help!
Btw: I'm using SQL-server for this.
I believe something like this should work:
UPDATE Claim
SET ClaimStatusID = alias.DamageApprovedStatusID
FROM (
SELECT DamageErrandCrossDamage.DamageID,
CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END AS DamageApprovedStatusID
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
) alias
WHERE Claim.ID = alias.DamageID
I guess it could be rewritten like this too:
UPDATE Claim
SET ClaimStatusID = CASE
WHEN DamageErrand.DamageApprovedStatusID = -1 THEN 0
WHEN DamageErrand.DamageApprovedStatusID = 0 THEN 4
WHEN DamageErrand.DamageApprovedStatusID = 1 THEN 2
ELSE '-'
END
FROM DamageErrand
INNER JOIN DamageErrandCrossDamage ON DamageErrand.ID = DamageErrandCrossDamage.DamageErrandID
INNER JOIN Claim ON DamageErrandCrossDamage.DamageID = Claim.ID

SQL Server stored procedure store multiple rows of SELECT statement result into single variable

I have a query with a SELECT statement that will return 2 or more rows as a result. How can I store these rows of data into a variable? Because I need the variable to check whether any of the rows is empty/null. How can I achieve this?
So far I've done this:
BEGIN
SELECT
#AINum = ISNULL(so.U_SI7_DPDocNum, 0), #soDocNum = so.DocNum
FROM
DLN1 doline
INNER JOIN
ORDR so ON doline.BaseRef = so.DocNum
WHERE
doline.DocEntry = #docEntry
WHILE(#AINum IS NOT NULL)
BEGIN
IF(#AINum <= 0)
BEGIN
SELECT #errCode = 003;
RETURN;
END
END
END
UPDATED query using EXISTS
SELECT #errCode = 003
WHERE NOT EXISTS (SELECT so.U_SI7_DPDocNum
FROM DLN1 doline
INNER JOIN ORDR so ON doline.BaseRef = so.DocNum
WHERE doline.DocEntry = #docEntry)
RETURN;
The #AINum will have to store multiple rows of data from the SELECT statement result. #errCode is an output variable.
Thank you.
-- initialize to 0
SELECT #errCode = 0;
-- assign value of 003 if it the DPDocNum is NULL or < 0
SELECT #errCode = 003
FROM DLN1 doline
INNER JOIN ORDR so ON doline.BaseRef = so.DocNum
WHERE doline.DocEntry = #docEntry
AND (so.U_SI7_DPDocNum IS NULL OR so.U_SI7_DPDocNum <= 0)

Function with in clause in where condition of SP decreasing the procedure performance

I have a procedure that has following functions in where condition:
select col1,col2,col3...
from table1
where
(dbo.GetFilStatus(et.SgDate,et.Speed,(SELECT COUNT(J.JId) FROM tbl_Nt J
inner JOIN tbl_NAssign JN ON JN.NNo =J.NNo
inner JOIN dbo.tbl_CStatus JS ON JS.CStatusID=J.CStatusID
INNER JOIN dbo.tbl_SStatus ss ON ss.SStatusID=JS.SStatusID
WHERE JN.DriID=et.DriID AND ss.SStatusID !=9),et.IgStatus)
in (Select val from Split('A,B,C,D,E',',')))
)
getfilstatus status contains the following code:-
if (#ServerDatetime <= DATEADD(MI,-10, GETDATE()))
BEGIN
IF(#xIgStatus = 'ON')
BEGIN
set #FilStatus= 'NoSignal'
END
ELSE
BEGIN
set #FilStatus= 'Stopped'
end
End
else IF(#xIgStatus = 'ON')
Begin
if(#Speed>5)
begin
if(#JCount<=0)
set #FilStatus='Moving'
else
set #FilStatus='Working'
end
else
begin
set #FilStatus= 'Idle'
end
End
else
Begin
set #FilStatus= 'Stopped'
end
RETURN #FilStatus
GetFilStatus always returns more than 10000 records. Sometimes its more than 100000. Its slowing the final output of query. Currently its taking more than 2 mins to return the output.
I am searching for any other option or any other trick using which the query performance can be increased and I could get the output in seconds.
Any suggestions? Any ideas?
It is better to put the split items in a temp table, as the split function needs to execute each time in the query iterations.
The third parameter has a complex inline query, i have created a temp table for the subset data and filtered necessary data inline.
SELECT S.items AS value
INTO #splited_items
FROM Split('A,B,C,D,E', ',') S;
SELECT Count(J.jid) AS Count_JId,
JN.driid AS DriID
INTO #joined_table
FROM tbl_nt J
INNER JOIN tbl_nassign JN
ON JN.nno = J.nno
INNER JOIN dbo.tbl_cstatus JS
ON JS.cstatusid = J.cstatusid
INNER JOIN dbo.tbl_sstatus ss
ON ss.sstatusid = JS.sstatusid
WHERE ss.sstatusid != 9
GROUP BY JN.driid
SELECT col1,
col2,
col3... from table1
WHERE ( dbo.Getfilstatus(et.sgdate, et.speed, (SELECT count_jid
FROM #joined_table
WHERE driid = et.driid),
et.igstatus)
IN (SELECT value
FROM #splited_items) )

Query taking too much

I am trying to execute updates while my condition returns results, the problem is that when i am testing the query it never finishes.
Here is the query;
While(select COUNT(*) from Agreement as agr where agr.Id in (
select toa.Id from Agreement_TemporaryOnceAgreement as toa where toa.Executed =1)
and agr.EndingDate is null) > 0
begin
DECLARE #AgreementID int;
SET #AgreementID =
(
select top 1 agr.id from Agreement as agr where agr.Id in (
select toa.Id from Agreement_TemporaryOnceAgreement as toa where toa.Executed =1)
and agr.EndingDate is null
)
update Agreement SET EndingDate = (
select tado.Date from TemporaryAgreementsDateOfExecution tado
where tado.AgreementId = CAST(#AgreementID AS INT))
where Agreement.Id = CAST(#AgreementID AS INT);
end;
You don't need a loop. A single update query resembling this should get the job done.
update a
set EndingDate = tado.date
from Agreement a join TemporaryAgreementsDateOfExecution tado
on a.AgreementId = tado.AgreementId
join Agreement_TemporaryOnceAgreement toa
on a.Id = toa.id
where EndingDate is null
and toa.Executed = 1
There might be slight variations depending on the RDBMS you are using.

Select from multiple tables with multiple where clauses

I am trying to write a stored procedure that will give a count of all the cases in a table that are not deleted, grouped by a CaseStatusID in another table, but only the cases that have a CaseStatusID that also isn't deleted. I also want it to return any CaseStatusID that does not have case related to it (i.e. a count of 0)
So far I have tried
Create Table #tCaseStatus (CaseStatusID int,CaseStatusDesc varchar(200) )
declare #NofCases int
declare #CaseStatusID int
declare #CaseStatusDesc varchar(200)
BEGIN
INSERT #tCaseStatus
Select CaseStatusID, CaseStatusDesc From dbo.CaseStatus Where IsDeleted = 0
Select #NofCases = Count(*) From #tCaseStatus
While (#NofCases > 0)
Begin
Select Top (1) #CaseStatusID = CaseStatusID, #CaseStatusDesc = CaseStatusDesc from #tCaseStatus
SELECT CaseStatusDesc, Count(CaseID) AS CountCases
FROM Cases inner join #tCaseStatus on Cases.CaseStatusID = #tCaseStatus.CaseStatusID
WHERE (IsDeleted = 0) AND Cases.CaseStatusID = #CaseStatusID
Group by #tCaseStatus.CaseStatusDesc
Set #NofCases = #NofCases - 1
Delete Top(1) from #tCaseStatus
End
END
AND
This returns the correct cases but excludes any of the CaseStatusDesc that have a count of 0
SELECT CaseStatus.CaseStatusDesc, COUNT(Cases.CaseID) AS CaseCount
FROM Cases FULL OUTER JOIN
CaseStatus ON Cases.CaseStatusID = CaseStatus.CaseStatusID
WHERE (CaseStatus.IsDeleted = 0) AND
(Cases.IsDeleted = 0)
GROUP BY CaseStatus.CaseStatusDesc, CaseStatus.CaseStatusID
ORDER BY CaseStatus.CaseStatusID
AND
this returns all the CaseStatusDesc's even the ones that are deleted
SELECT CaseStatus.CaseStatusDesc, COUNT(CASE
WHEN CaseStatus.IsDeleted = 0 THEN 'ok'
WHEN Cases.IsDeleted = 0 THEN 'ok'
Else null
END) AS [Case]
FROM Cases FULL OUTER JOIN CaseStatus ON Cases.CaseStatusID = CaseStatus.CaseStatusID
GROUP BY CaseStatus.CaseStatusDesc, CaseStatus.CaseStatusID
Order By CaseStatus.CaseStatusID asc
But I cant seem to get the desired results
Is this what you're after?
select
casestatus.casestatusid,
casestatusdesc,
COUNT(caseid)
from casestatus
left join cases
on casestatus.casestatusid = cases.casestatusid
and cases.isdeleted=0
where
casestatus.isdeleted=0
group by
casestatus.casestatusid,
casestatusdesc