CASE
WHEN @FilterBy = 5 AND d.TransactionTime >= CAST(@Value1 AS DATE)
AND d.TransactionTime <= CAST(@Value2 AS DATE) THEN 1
ELSE 0
END = 1
Transact-SQL stored procedure with conditional "AND" logic
-
18-07-2023 - |
문제
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
해결책
다른 팁
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