Transact-SQL stored procedure with conditional "AND" logic - sql

I'm working on a stored procedure that is used to filter a grid based on criteria entered by the user. Among the possible criteria they may choose to see transactions that were done between a certain begin and end date. I pass 4 input parameters to the proc - #ClientKey, the client requesting the info, #FilterBy (this is the selected value from a dropdown list in ASP.NET, and essentially tells the proc whether the user is selecting to filter by name, address, date, etc. In this case the #FilterBy value for date is 5), #Value1, which in this instance would be the begin date, and #Value2, which in this instance would be the end date.
In pseudo-code, what I want is:
SELECT ABunchOfColumns
FROM SomeJoinedTables
WHERE SomeCriteria
AND CASE #FilterBy
WHEN 5 THEN d.TransactionTime >= CAST(#Value1 AS Date) AND d.TransactionTime <= CAST(#Value2 AS Date)
Below is the full query. I hope that someone who is more savvy than me with SQL can sort out what I'm trying to do and offer a solution.
Thanks in advance!
#ClientKey int,
#FilterBy int,
#Value1 varchar(150),
#Value2 varchar(150)
AS
BEGIN
SELECT d.pKey AS PaymentKey, d.CaseKey, d.InvoiceID, d.AuthorizationCode, d.TransactionID, d.PaymentType, d.Amount, d.ExpirationDate, d.CardType, d.BankName, d.AccountNumber,
d.AccountType, c.Name, c.Address1, c.City, c.State, c.Zip, cs.PAmount, cs.TranCode, cs.TranDate, cs.[Desc] AS PaymentDescription, cc.[Desc] AS ChargeCodeDescription,
d.TransactionTime, a.Name AS AssociationName, d.PaymentType, c.ClientPaymentID
FROM DebtorPayment d INNER JOIN Cases c
ON d.CaseKey = c.pKey
AND d.ClientKey = c.ClientKey
INNER JOIN CaseSumm cs
ON d.CaseKey = cs.CaseKey
AND d.pKey = cs.Batch
AND d.ClientKey = cs.ClientKey
INNER JOIN ChargeCodes cc
ON c.ClientKey = cc.ClientKey
AND cs.TranCode = cc.RefNum
INNER JOIN AssnCtrl a
ON c.AssnKey = a.pKey
WHERE c.ClientKey = #ClientKey
AND d.AmountAllocated > 0
AND d.TransactionStatus = 'Successful'
AND c.Address1 LIKE CASE
WHEN #FilterBy = 1 THEN '%' + #Value1 + '%'
ELSE c.Address1
END
AND d.Amount = CASE
WHEN #FilterBy = 2 THEN #Value1
ELSE d.Amount
END
AND a.pKey = CASE
WHEN #FilterBy = 3 THEN CAST(#Value1 AS INT)
ELSE a.pKey
END
AND c.ClientPaymentID = CASE
WHEN #FilterBy = 4 THEN #Value1
ELSE c.ClientPaymentID
END
<ProblemArea>
AND CASE #FilterBy
WHEN 5 THEN d.TransactionTime >= CAST(#Value1 AS Date) AND d.TransactionTime <= CAST(#Value2 AS Date)
END
</ProblemArea>
AND c.LName LIKE CASE
WHEN #FilterBy = 6 THEN '%' + #Value1 + '%'
ELSE c.LName
END
ORDER BY d.TransactionTime DESC
END

CASE
WHEN #FilterBy = 5 AND d.TransactionTime >= CAST(#Value1 AS DATE)
AND d.TransactionTime <= CAST(#Value2 AS DATE) THEN 1
ELSE 0
END = 1

Do you mean something like the following?
You might find this link useful too.
Haven't tested the code, just proposing idea - and writing code like this has always felt "wrong" to me - perhaps someone could offer better.
CREATE PROC MyProc
#ClientKey int,
#FilterBy int,
#Value1 varchar(150),
#Value2 varchar(150)
-- NB WITH RECOMPILE, see link (above)
WITH RECOMPILE AS
BEGIN
SET NOCOUNT ON;
SELECT *
FROM ...
WHERE
Col1 = CASE
WHEN #FilterBy = 1 THEN #Value1
ELSE Col1
END
AND
1 = CASE
WHEN #FilterBy = 2 AND Col2 > #Value1 AND Col3 < #Value2 THEN 1
WHEN #FilterBy = 2 AND NOT (Col2 > #Value1 AND Col3 < #Value2) THEN 0
ELSE 1
END
END

Related

Stored procedure sometimes takes a long time to execute query in SQL Server

I have strange issue and I am getting more confused about this. I am using UWP on the .NET framework and using SQL Server as database. The problem is my application working too much slow and when I check my stored procedure execution time then I am notice that may be a problem is from the database stored procedure side.
My stored procedure sometimes takes 4-5 seconds to execute and sometimes takes more like 15-16 seconds and sometimes it takes more than 1 minute.
My questions are:
Why is it taking a lot more time sometimes, but not every time?
How can I solve this issue and boost my application execution time?
This is the stored procedure:
ALTER PROCEDURE [dbo].[SPNAME]
#HouseID INT,
#FromDate DATETIME,
#ToDate DATETIME,
#PageNumber INT,
#PageSize INT,
#RollID INT
AS
BEGIN
DECLARE #RoomID INT = 0
DECLARE #UnitID INT = 0
DECLARE #HouseCode INT = 0
DECLARE #StartRow INT
DECLARE #EndRow INT
SET #StartRow = #PageNumber
SET #StartRow = ((#StartRow-1) * #PageSize) + 1
SET #EndRow = (#StartRow + #PageSize) - 1;
IF OBJECT_ID('tempdb.dbo.#TableName') IS NOT NULL
DROP TABLE dbo.#TableName
SELECT
#HouseCode = [HouseCode],
#UnitID = UnitId
FROM
[dbo].[tblHouse]
WHERE
[HouseId] = #HouseID
SELECT #RoomID = RoomCode
FROM [dbo].[tblUnit] u
LEFT JOIN tblRoom h ON u.RoomID = h.Room
WHERE UnitID = #UnitID
SELECT MAX(RoNum) RoNum
INTO dbo.#tableName
FROM [dbo].[TAbleNAme]
WHERE FanId = #HouseCode
AND InActive = 0
AND ((InactivatedOn IS NULL AND StopDate IS NULL)
OR (ISNULL(InactivatedOn, StopDate) BETWEEN #FromDate AND #ToDate)
OR (ISNULL(InactivatedOn,StopDate) >= #ToDate))
AND (FirstFillDate <= #ToDate)
GROUP BY
OrigRoNum
SELECT
K.Topic, K.Comment, K.RoNum
INTO
#TmptblRoCom
FROM
[dbo].[TableNAme] K
LEFT JOIN
#TableName T ON K.RoNum = T.RoNum
WHERE
K.Topic = 'Nar Auto'
AND ISNUMERIC(SUBSTRING(K.Comment, 0, 3)) = 1
SELECT ButtonTypeID, ISNULL(SortOrder, 17) AS SortOrder
INTO dbo.#TableName
FROM [dbo].[TAbleName]
WHERE NHID = #RoomID AND NHSortID = 29
SELECT
DIN,
'LU: ' + LTRIM(RTRIM(ReasonCode)) +
'Exp:' + ISNULL(FORMAT(ExpiryDate, 'dd/MM/yyyy'), 'Indefinite') AS HLCode
INTO
dbo.#TableName
FROM
[dbo].[TableNAme]
WHERE
PatID = #HouseCode
AND (ExpiryDate IS NULL OR ExpiryDate > GETDATE())
SELECT
X.DgID AS DumbID,
X.ID AS RID,
CASE
WHEN DR.BandName IS NULL
THEN '#' + dm.Description
ELSE CONCAT(BandName, ' ', strength)
END AS DugName,
StrengthType, FormType,
CASE
WHEN GericName IS NULL
THEN
CASE
WHEN BandName IS NULL
THEN '#' + dm.Description
ELSE CONCAT(DR.BandName, ' ', DR.strength)
END
ELSE CONCAT(DR.GericName, ' ', DR.strengthTypr)
END AS GericName,
DR.[Description],
dbo.GetDirectionWithFullForm (X.IG,' ') AS Direction,
CAST(X.RoNum AS BIGINT) AS RoNum,
FORMAT(X.FirstFillDate,'dd/MM/yyyy') AS FirstFillDate,
FORMAT(X.LastFillDate,'dd/MM/yyyy') AS DugOrderDate,
ISNULL(TP.[ID],0) AS RollID,
TP.[Cont] AS Cont,
TP.[DisContinue] AS Disc,
TP.[Hold] AS Hold,
CAST(m.OrderType AS INT) AS OrderType,
pl.HLCode,
rc.Comment,
TP.[Comments]
FROM
dbo.#TAbleNAme rn
INNER JOIN
[dbo].[RollRx] X ON rn.RoNum = X.RoNum
INNER JOIN
[dbo].[RollDg] DR ON X.[DgID] = DR.ID
LEFT JOIN
[dbo].[RollDgMix] DM ON X.MixID = DM.ID
LEFT JOIN
[dbo].[RollPreviousNumber] TP ON X.DrgID = TP.[RollMedicationID]
AND X.[ID] = TP.[RoID]
AND TP.[HouseID] = #HouseID
AND TP.[TableName] = #RollID
LEFT JOIN
dbo.#TableNAme m ON m.TypeID = X.TypeID
LEFT JOIN
dbo.#TableName pl ON pl.DNNUM = X.DNNUM
LEFT JOIN
dbo.#TableName rc ON rc.RoNum = X.RoNum
END
Execution Plan
Yes sounds like parameter sniffing or lack of memory issue (this has made it block for me at times when I am running to much on my box), look at the execution plan.
Run the stored proc with your parameters and see if there is a difference here, by right clicking on the execution plan select, below shows an example.

Best performance for paging query when using multiple statements in sql?

It is a bit complicated query but let me elaborate,
i have got multiple filter parameters in my procedure,
also a view named Vw1 and its regarded my main object in query that most of the filter parameters are filtered against this view that is located in another server,then i need to compare this view to another table and check two sides columns for possible conflict and then check if there is any conflict.
you can see my query below
ALTER PROC [dbo].[spGetAyandehVagozariWithConflict]
#Take INT,
#Skip INT,
#FromVagozariDate NVARCHAR(10),
#ToVagozariDate NVARCHAR(10),
#OrderBankCode NVARCHAR(4)=null,
#OrderBrCode NVARCHAR(7)=null,
#BenefBrCode NVARCHAR(4)=null,
#FromAmount NVARCHAR(50)=null,
#ToAmount NVARCHAR(50)=null,
#CheqSerie NVARCHAR(50)=null,
#CheqSerial NVARCHAR(10)=null,
#CheqStatus NVARCHAR(4)=null,
#CreditorNationalCode VARCHAR(20)=NULL,
#CheqType NVARCHAR(4)=null,
#BenefAccn NVARCHAR(13)=null,
#FromMatDate NVARCHAR(10)=null,
#ToMatDate NVARCHAR(10)=null,
#FromTaeenVaziatDate NVARCHAR(10)=null,
#ToTaeenVaziatDate NVARCHAR(10)=NULL,
#HasConflict VARCHAR(4)=null,
#TotalCnt INT OUTPUT,
#SUM BIGINT OUTPUT
AS
BEGIN
DECLARE #Query NVARCHAR(MAX)=''
IF(NULLIF(#FromVagozariDate,'') IS null)
SET #FromVagozariDate='NULL'
IF(NULLIF(#ToVagozariDate,'') IS null)
SET #ToVagozariDate='NULL'
IF(NULLIF(#OrderBrCode,'') IS null)
SET #OrderBrCode='NULL'
IF(NULLIF(#OrderBankCode,'') IS null)
SET #OrderBankCode='NULL'
IF(NULLIF(#BenefBrCode,'') IS null)
SET #BenefBrCode='NULL'
IF(NULLIF(#FromAmount,'') IS null)
SET #FromAmount='NULL'
IF(NULLIF(#ToAmount,'') IS null)
SET #ToAmount='NULL'
IF(NULLIF(#CheqSerie,'') IS null)
SET #CheqSerie='NULL'
IF(NULLIF(#CheqSerial,'') IS null)
SET #CheqSerial='NULL'
IF(NULLIF(#CheqStatus,'') IS null)
SET #CheqStatus='NULL'
IF(NULLIF(#CheqType,'') IS null)
SET #CheqType='NULL'
IF(NULLIF(#BenefAccn,'') IS null)
SET #BenefAccn='NULL'
IF(NULLIF(#ToMatDate,'') IS null)
SET #ToMatDate='NULL'
IF(NULLIF(#FromMatDate,'') IS null)
SET #FromMatDate='NULL'
IF(NULLIF(#FromTaeenVaziatDate,'') IS null)
SET #FromTaeenVaziatDate='NULL'
IF(NULLIF(#ToTaeenVaziatDate,'') IS null)
SET #ToTaeenVaziatDate='NULL'
IF(NULLIF(#HasConflict,'') IS null)
SET #HasConflict='NULL'
IF(NULLIF(#CreditorNationalCode,'') IS null)
SET #CreditorNationalCode='NULL'
IF #FromVagozariDate<>'NULL'
BEGIN
SET #FromVagozariDate=REPLACE(#FromVagozariDate,'/','')
END
IF #ToVagozariDate<>'NULL'
BEGIN
SET #ToVagozariDate=REPLACE(#ToVagozariDate,'/','')
END
IF #FromMatDate<>'NULL'
BEGIN
SET #FromMatDate=REPLACE(#FromMatDate,'/','')
END
IF #ToMatDate<>'NULL'
BEGIN
SET #ToMatDate=REPLACE(#ToMatDate,'/','')
END
IF #FromTaeenVaziatDate<>'NULL'
BEGIN
SET #FromTaeenVaziatDate=REPLACE(#FromTaeenVaziatDate,'/','')
SET #FromTaeenVaziatDate=SUBSTRING(#FromTaeenVaziatDate,3,6)
END
IF #ToTaeenVaziatDate<>'NULL'
BEGIN
SET #ToTaeenVaziatDate=REPLACE(#ToTaeenVaziatDate,'/','')
SET #ToTaeenVaziatDate=SUBSTRING(#ToTaeenVaziatDate,3,6)
END
IF #OrderBankCode<>'NULL'
BEGIN
--SET #OrderBankCode='0'+#OrderBankCode;
SET #OrderBankCode=dbo.LeftPad(#OrderBankCode,'0',3)
END
IF(#BenefBrCode<>'NULL')
BEGIN
SET #BenefBrCode=dbo.LeftPad(#BenefBrCode,'0',4)
END
IF(#OrderBrCode<>'NULL')
BEGIN
SET #OrderBrCode=dbo.LeftPad(#OrderBrCode,'0',4)
END
SET #Query=#Query+N'
SELECT *
INTO #Vw1
FROM [LinkedServer].DbName.dbo.Vw1 vd
where (vd.mat_date BETWEEN '+''''+#FromMatDate+''''+' AND'+''''+ #ToMatDate+''''+' OR ('+''''+#FromMatDate+''''+' =''NULL'' AND '+''''+#ToMatDate+''''+' =''NULL'' )) AND
(dbo.LeftPad(vd.order_bank_code,''0'',3)= '+''''+#OrderBankCode+''''+' OR '+''''+#OrderBankCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.order_brcode,''0'',4)= '+''''+#OrderBrCode+''''+' OR '+''''+#OrderBrCode+''''+' =''NULL'') AND
(dbo.LeftPad(vd.Benef_br_code,''0'',4)= '+''''+#BenefBrCode+''''+' OR '+''''+#BenefBrCode+''''+' =''NULL'') AND
(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10) BETWEEN '+''''+#FromAmount+''''+' AND '+''''+#ToAmount+''''+' OR ('+''''+#FromAmount+''''+' =''NULL'' AND '+''''+#ToAmount+''''+' =''NULL'')) AND
(RTRIM(LTRIM(vd.chq_serie))= '+''''+#CheqSerie+''''+' OR '+''''+#CheqSerie+''''+' =''NULL'') AND
(RTRIM(LTRIM(vd.chq_serial))= '+''''+#CheqSerial+''''+' OR '+''''+#CheqSerial+''''+' =''NULL'') AND
(vd.Chq_stat= '+''''+#CheqStatus+''''+' OR '+''''+#CheqStatus+''''+' in (''NULL'',''-1'')) AND
(vd.chq_type= '+''''+#CheqType+''''+' OR '+''''+#CheqType+''''+' =''NULL'') AND
(vd.benef_acno= '+''''+#BenefAccn+''''+' OR '+''''+#BenefAccn+''''+' =''NULL'') AND
((vd.taeen_vaziat_date is null AND ('+''''+#CheqStatus+''''+'=''-1'')) or('+''''+#CheqStatus+''''+'<>''-1'') ) AND
(vd.vagozari_date BETWEEN '+''''+#FromVagozariDate+''''+' AND '+''''+#ToVagozariDate+''''+' OR ('+''''+#FromVagozariDate+''''+' =''NULL'' AND '+''''+#ToVagozariDate+''''+' =''NULL'')) AND
(vd.taeen_vaziat_date BETWEEN '+''''+#FromTaeenVaziatDate+''''+' AND '+''''+#ToTaeenVaziatDate+''''+' OR ('+''''+#ToTaeenVaziatDate+''''+' =''NULL'' AND '+''''+#FromTaeenVaziatDate+''''+' =''NULL''))
order by system_no
select distinct cast(benef_acno as bigint) benef_acno
into #acno
from #Vw1
select ACNO,CUSTNO
into #ACTINFO
from [LinkServer1].[Db1].[dbo].[ACTINFO] af
where accno_id in (select * from #acno)
select [ECONOMIC-CODE],CUSTNO,FIRSTNAME +'' ''+LASTNAME CUSTNAME
into #CUSTINFO
from [LinkServer1].[Db1].[dbo].[CUSTINFO]
where CustNo_Id in (select cast(CUSTNO as bigint) from #ACTINFO)
SELECT
vd.*,
ct.Title CheqTypeTitle,
af.CUSTNO,cf.CUSTNAME,
--'''' as CUSTNO,'''' CUSTNAME,
cs.Status CheqStatusTitle,
av.Id AyandehVagozariId,
p.ParticipantName BenefBankName,
CASE WHEN ISNULL(vd.vagozari_date,'''') <> COALESCE(REPLACE(av.VagozariDate,''/'',''''),vd.vagozari_date,'''') THEN 1 ELSE 0 END VagozariDateHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_bank_code,''0'',3),'''') <> COALESCE(av.Order_Bank_Code,dbo.LeftPad(vd.order_bank_code,''0'',3),'''') THEN 1 ELSE 0 END OrderBankCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.order_brcode,''0'',4),'''') <> COALESCE(av.Order_brCode,dbo.LeftPad(vd.order_brcode,''0'',4),'''') THEN 1 ELSE 0 END OrderBrCodeHasConflict,
CASE WHEN ISNULL(dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') <> COALESCE(av.Benef_Br_Code,dbo.LeftPad(vd.Benef_br_code,''0'',4),'''') THEN 1 ELSE 0 END BenefBrCodeHasConflict,
CASE WHEN ISNULL(substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') <> COALESCE(av.Amount,substring(vd.amount, patindex(''%[^0]%'',vd.amount), 10),'''') THEN 1 ELSE 0 END AmountHasConflict,
CASE WHEN ISNULL(vd.chq_serie,'''') <> COALESCE(av.Chq_serie,vd.chq_serie,'''') THEN 1 ELSE 0 END CheqSerieHasConflict,
CASE WHEN ISNULL(RTRIM(LTRIM(vd.chq_serial)),'''') <> COALESCE(av.Chq_Serial,RTRIM(LTRIM(vd.chq_serial)),'''') THEN 1 ELSE 0 END CheqSerialHasConflict,
CASE WHEN ISNULL(vd.chq_type,'''') <> COALESCE(av.Chq_Type,vd.chq_type,'''') THEN 1 ELSE 0 END CheqTypeHasConflict,
CASE WHEN ISNULL(vd.benef_acno,'''') <> COALESCE(av.Benef_Acno,vd.benef_acno,'''') THEN 1 ELSE 0 END BenefAcnoHasConflict,
CASE WHEN ISNULL(vd.mat_date,'''') <> COALESCE(REPLACE(av.Mat_Date,''/'',''''),vd.mat_date,'''') THEN 1 ELSE 0 END MatDateHasConflict,
CASE WHEN ISNULL(cf.CUSTNO,'''') <> COALESCE(av.CUSTNO,cf.CUSTNO COLLATE DATABASE_DEFAULT,'''') THEN 1 ELSE 0 END CustNoHasConflict,
--CASE WHEN ISNULL(vd.taeen_vaziat_date,'''') <> COALESCE(av.Taeen_Vaziat_Date,vd.taeen_vaziat_date,'''') THEN 1 ELSE 0 END TaeenVaziatDateHasConflict,
0 as TaeenVaziatDateHasConflict,
CASE WHEN ISNULL(vd.Chq_stat,'''') <> COALESCE(av.Chq_Status,vd.Chq_stat,'''') THEN 1 ELSE 0 END CheqStatusHasConflict
--0 as VagozariDateHasConflict,
--0 as OrderBankCodeHasConflict,
--0 as OrderBrCodeHasConflict,
--0 as BenefBrCodeHasConflict,
--0 as AmountHasConflict,
--0 as CheqSerieHasConflict,
--0 as CheqSerialHasConflict,
--0 as CheqTypeHasConflict,
--0 as BenefAcnoHasConflict,
--0 as MatDateHasConflict,
--0 as TaeenVaziatDateHasConflict
INTO #temp
FROM #vw_faranam_vagozari_chakavak vd
LEFT JOIN #ACTINFO af on vd.benef_acno=af.ACNO COLLATE Arabic_CI_AS
LEFT JOIN #CUSTINFO cf on af.CUSTNO=cf.CUSTNO COLLATE Arabic_CI_AS
LEFT JOIN [AyandehVagozari] av ON av.SystemNo=vd.system_no
LEFT JOIN [Cheque_Type_Biha] ct ON ct.Code=vd.chq_type
LEFT JOIN [ChequeStatusForBiha] cs ON cs.Id=vd.Chq_stat
LEFT JOIN [Participant] p ON ''0''+p.ParticipantCode=vd.order_bank_code
WHERE (cf.[ECONOMIC-CODE]= '+''''+#CreditorNationalCode+''''+' OR '+''''+#CreditorNationalCode+''''+' =''NULL'')
order by vd.system_no
DELETE t FROM(
SELECT *,ROW_NUMBER() OVER(partition by system_no order by AyandehVagozariId desc) rn FROM
#temp
)t
where rn>1
SELECT *,
case when (VagozariDateHasConflict=1 or OrderBankCodeHasConflict=1 or OrderBrCodeHasConflict =1 OR BenefBrCodeHasConflict=1
or AmountHasConflict=1 or CheqSerieHasConflict=1 or CheqSerialHasConflict=1 or CustNoHasConflict=1
or CheqStatusHasConflict=1 or CheqTypeHasConflict=1 or BenefAcnoHasConflict=1 or MatDateHasConflict=1 or TaeenVaziatDateHasConflict=1)
then 1 else 0 end HasConflict
INTO #TmpResult
FROM #temp
order by system_no
--here is where i filter my last parameter but it seems too late..because alot of records already involved !
SELECT *,ROW_NUMBER() over (ORDER BY system_no) RowNumber
into #finalTemp
FROM
#TmpResult
where (HasConflict=1 and '+''''+#HasConflict+''''+'=''1'')
OR (HasConflict=0 and '+''''+#HasConflict+''''+'=''0'')
OR ('+''''+#HasConflict+''''+'=''NULL'')
order by system_no
SELECT #Total=##ROWCOUNT
select #Sum=isnull(SUM(cast(amount as bigint)),0) from
#finalTemp
select * from
#finalTemp
WHERE RowNumber >'+CAST(#Skip AS NVARCHAR(10))+' AND RowNumber<=('+CAST(#Skip+#Take AS NVARCHAR(10))+')
'
PRINT #Query
EXEC sp_executesql #Query,N'#Total int output,#Sum bigint output',#TotalCnt OUTPUT,#SUM OUTPUT
END
due to performance issues i had to write it in dynamic way,But the problem is that i could not wrap my head around paging in this query, bacause as you see i should put paging line in the end of query because #HasConflict parameters exist and i cannot check it earlier,and in this way my paging seems pointless because i'm dealing with huge load of data ...
also i cannot use offset for paging because my sql version is too old ...

SQL CASE wrong output

I have this weird encounter using CASE in sql 2014.
This is my query:
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE dbo.GetFunctionAge(C.Birthdate)
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
this is the output:
Here is the GetFunctionAge function if you might ask.
IF EXISTS (
SELECT *
FROM dbo.sysobjects
WHERE ID = OBJECT_ID(N'[dbo].[GetFunctionAge]') AND
xtype in (N'FN', N'IF', N'TF'))
DROP FUNCTION [dbo].[GetFunctionAge]
GO
CREATE FUNCTION [dbo].[GetFunctionAge](#BirthDate DATETIME)
RETURNS INT
AS
BEGIN
DECLARE #Age INT
IF(#BirthDate = '1753-01-01 00:00:00.000')
BEGIN
SET #Age = 0
END
ELSE
BEGIN
SET #Age = DATEDIFF(hour,#BirthDate,GETDATE())/8766
END
RETURN #Age
END
GO
Question:
Why is Column Age in my output is 0which should be ''?
I added (No column name) to show that its output is 0 so my expected output base from my case condition is '' not 0
I didn't receive any error regarding inconsistency of data so why is case behaving like that?
Thanks for those who could clarify this to me.
SELECT
(CASE
WHEN a.ageint = 0 THEN ''
ELSE cast(a.ageint as varchar(3))
END) AS Age
, a.ageint
, c.Birthdate
FROM Client as C
CROSS APPLY (
SELECT
ISNULL(dbo.GetFunctionAge(C.Birthdate), 0) AS ageint
) AS a
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
;
You can cast it into varchar so you can return ' '.
SELECT (CASE WHEN dbo.GetFunctionAge(C.Birthdate) = 0
THEN '' ELSE Cast(dbo.GetFunctionAge(C.Birthdate) as varchar(5))
END) AS Age
,dbo.GetFunctionAge(C.Birthdate)
,c.Birthdate
FROM Client C
WHERE ClientID = '34d0d845-e3a6-4078-8936-953ff3378eac'
But If you wish to remain your Age column in data type int.
You could just use NULL instead of ' '

Assign to a T-SQL variable from a CASE statement

I'd like to assign some variables inside a query that uses CASE statements for it's columns. Not quite sure how to do this, having trouble finding the right syntax.
This is what I have so far, but it's got syntax errors.
-- set #theID and #theName with their appropriate values
select top (1)
#theID = (Case when B.ID IS NULL then A.ID else B.ID END) ,
#theName = (Case when B.Name IS NULL then A.Name else B.Name END)
from B left join A on A.ID = B.ID where ...
What's the correct place/way to stick those variables in there?
The example you've given should work. You can assign to variables from a case statement. Just pretend that the entire CASE..WHEN..THEN..ELSE..END block is a field. Here is a generic example:
declare #string1 nvarchar(100) = null
declare #string2 nvarchar(100) = null
select
#string1 = case when 1=1 then 'yes' else 'no' end
,#string2 = case when 1=0 then 'yes' else 'no' end
print 'string1 = ' + #string1
print 'string2 = ' + #string2
Gives:
string1 = yes
string2 = no
Can you tell us what specific error(s) you are getting?
You could probably do this more easily using ISNULL or COALESCE:
select top (1)
#theID = ISNULL(B.ID, A.ID),
#theName = ISNULL(B.Name, A.Name),
from B left join A on A.ID = B.ID where ...
DECLARE #SmallBlindSeatId INT
DECLARE #BigBlindSeatId INT
DECLARE #DealerSeatId INT
DECLARE #NextTurn INT
SELECT #DealerSeatId=( CASE WHEN BlindsInfo=1 THEN SeatId ELSE #DealerSeatId END ),
#SmallBlindSeatId=( CASE WHEN BlindsInfo=2 THEN SeatId ELSE #SmallBlindSeatId END),
#BigBlindSeatId=( CASE WHEN BlindsInfo=3 THEN SeatId ELSE #BigBlindSeatId END),
#NextTurn=( CASE WHEN NEXTTURN=1 THEN SeatId ELSE #NextTurn END)
FROM ABC WHERE TESTCASEID=1
PRINT(#DealerSeatId)
PRINT(#SmallBlindSeatId)
PRINT(#BigBlindSeatId)
PRINT (#NextTurn)

Condition in sql query

I want to insert in sql query something like that:
Select * from Users where id=[if #userId>3 then #userId else "donnt use this condition"] and Name=[switch #userId
case 1:"Alex"
case 2:"John"
default:"donnt use this condition"];
How can i do it?
yet another similar question
When showAll is false it works ok but when showAll is true it returns nothing. Why and how to make it working right? IsClosed column has a bit type.
Select * from orders where IsClosed=CASE WHEN #showAll='false' THEN 'false' ELSE NULL END;
This will perform horribly:
Select *
from Users
where (#userid > 3 AND id = #userId)
OR (#userId BETWEEN 1 AND 2 AND name = CASE
WHEN #userId = 1 THEN 'Alex'
ELSE 'John'
END)
The best performing option is dynamic SQL:
SQL Server 2005+
DECLARE #SQL NVARCHAR(4000)
SET #SQL = 'SELECT u.*
FROM USERS u
WHERE 1 = 1 '
SET#SQL = #SQL + CASE
WHEN #userId > 3 THEN ' AND u.id = #userId '
ELSE ''
END
SET#SQL = #SQL + CASE #userId
WHEN 1 THEN ' AND u.name = ''Alex'' '
WHEN 2 THEN ' AND u.name = ''John'' '
ELSE ''
END
BEGIN
EXEC sp_executesql #SQL, N'#userId INT', #userId
END
For more info on SQL Server's dynamic SQL support, read "The Curse and Blessings of Dynamic SQL"
Select *
from Users
where id = CASE WHEN #userId>3 THEN #userId ELSE NULL END
OR name = CASE WHEN #userId = 1 THEN 'Alex' WHEN #UserId = 2 THEN 'John' ELSE NULL END
Please try this:
select *
from Users
where id = (case when #userId > 3 then #userId
else id end)
and Name = (case cast(#userId as varchar)
when '1' then 'Alex'
when '2' then 'John'
else Name end)
Or I think this will perform better:
select aa.*
from (select *
, case when #userId > 3 then #userId
else id end as UserID
, case cast(#userId as varchar)
when '1' then 'Alex'
when '2' then 'John'
else Name end as UserName
from Users) aa
where aa.id = aa.UserID
and aa.Name = aa.UserName
You might want to define each field that you only need on your select, instead of using asterisk(*).