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

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)

Related

Conditionally adding a column in a SQL query

I'm trying to add a conditional SELECT column in a query and I'm having trouble writing it out:
SELECT v.GLTypeID,
v.something,
v.somethignElse,
CASE WHEN (SELECT TOP 1 Value FROM InterfaceParam WHERE InterfaceId = 0 AND Descr = 'gf') = 1 THEN a.CreditID ELSE NULL END AS CreditMemoID
FROM vGLDetails2 v
....
LEFT OUTER JOIN AssociationFund f
ON v.FundID = f.FundID
LEFT JOIN dbo.APLedger a ON v.RelID = a.APLedgerID AND v.RelTypeID IN (39, 40)
....
ORDER BY v.Code;
The query above works, however if the CASE statement is still returning an additional column regardless of the result of the subquery. How can I remove it if the subquery doesn't return a row?
How can I do this?
Change the location of AS. For example:
SELECT v.GLTypeID,
v.something,
v.somethignElse,
CASE WHEN (
SELECT TOP 1 Value
FROM InterfaceParam
WHERE InterfaceId = 0 AND Descr = 'creditMemo') = 1
THEN a.CreditID -- AS is not valid here
END AS CreditMemoID -- AS is valid here
FROM vGLDetails2 v
....
LEFT OUTER JOIN AssociationFund f
ON v.FundID = f.FundID
LEFT JOIN dbo.APLedger a ON v.RelID = a.APLedgerID AND v.RelTypeID IN (39, 40)
....
ORDER BY v.Code;
Note: I removed ELSE NULL since this is the default behavior of CASE.

how do I loop through a set of records

how do I loop through a set of records from a select?
Here is my stored procedure query:
ALTER PROCEDURE [dbo].[procedure_rastavljanjeOtpremnica] (#radniNalogID INT) AS
DECLARE #bool BIT = 0
IF(#bool = 'FALSE')
BEGIN
SELECT ROW_NUMBER() OVER(ORDER BY S.PuniNaziv) AS num_row, S.PuniNaziv, a.KolicinaMjeracaIElektronike FROM ArtikliUslugeNaloga a
INNER JOIN SifreArtikala S ON S.Id = a.Artikal1Id
INNER JOIN UslugeNaloga ON UslugeNaloga.Id = a.UslugeNalogaId
WHERE a.RobaSkart = #bool AND UslugeNaloga.RadniNalogID = #radniNalogID
END
The result is:
now_row PuniNaziv Kolicina
1 Komunik internet jed s ugrađ WIFi sensoNET 3
2 Ventil tahret DN15 (1/2") 5
3 Vodokotlić Geberit 1
So what I need to do is to add another column that will print KOM for every row,
This is the result that I am looking for:
now_row PuniNaziv Kolicina Jedinia mjere
1 Komunik internet jed s ugrađ WIFi sensoNET 3 Kom
2 Ventil tahret DN15 (1/2") 5 Kom
3 Vodokotlić Geberit 1 Kom
Can anyone give me idea how to do this
There is no need to "loop". Just add the column to your query:
SELECT ROW_NUMBER() OVER (ORDER BY S.PuniNaziv) AS num_row,
S.PuniNaziv, a.KolicinaMjeracaIElektronike,
'Kom' as Jedinia_mjere
FROM ArtikliUslugeNaloga a JOIN
SifreArtikala S
ON S.Id = a.Artikal1Id JOIN
UslugeNaloga
ON UslugeNaloga.Id = a.UslugeNalogaId
WHERE a.RobaSkart = #bool AND
UslugeNaloga.RadniNalogID = #radniNalogID;
Note: If you want to ensure that the rows are returned in the order specified by num_row, you should add ORDER BY num_row to the query.

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) )

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

UDF not returning the same value as select contained in UDF

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!!!!