Reputation: 3669
Based on a declared variable, is it possible to switch between not equal and equal in the where clause?
For example, if the variable @InState is set to true, then return all the addresses with a state equal to 'CA', if false, return all of the addresses with states <> 'CA'.
Code:
DECLARE @InState bit
SET @InState = 1
SELECT *
FROM dbo.tAddresses ADDR
WHERE ADDR.Status = 'A'
AND ADDR.State =
CASE WHEN @InState = 1
THEN
'CA'
ELSE
''
The ELSE in the code above, returns every state including 'CA'. I need to return every other state, not equal to 'CA'.
Upvotes: 1
Views: 589
Reputation: 45096
Not a where clause but I think it is sargable
SELECT ADDR.*
FROM dbo.tAddresses ADDR
left join dbo.tAddresses ADDRin
on ADDRin.id = ADDR.id
and ADDRin.State = 'CA'
and @InState = 1
left join dbo.tAddresses ADDRout
on ADDRout.id = ADDR.id
and ADDRout.State <> 'CA'
and @InState = 0
WHERE ADDR.Status = 'A'
AND (ADDRin.id is not null or ADDRout.id is not null)
SELECT ADDR.*
FROM dbo.tAddresses ADDR
where ADDR.Status = 'A'
and ADDR.State = 'CA'
and @InState = 1
UNION ALL
SELECT ADDR.*
FROM dbo.tAddresses ADDR
where ADDR.Status = 'A'
and ADDR.State <> 'CA'
and @InState <> 1
Upvotes: 1
Reputation: 8113
I'd try to avoid CASE
statements in the WHERE
clause and go for something like this;
Test Data;
DECLARE @Instate bit; SET @Instate = 1
CREATE TABLE #Addresses (ID int, State varchar(2), Status varchar(2))
INSERT INTO #Addresses (ID, State, Status)
VALUES
(1,'CA','A')
,(2,'NY','A')
,(3,'CA','A')
,(4,'NJ','A')
,(5,'FL','A')
,(6,'CA','A')
,(7,'ND','A')
Query
DECLARE @InState bit
SET @InState = 1
SELECT *
FROM #Addresses ADDR
WHERE ADDR.Status = 'A'
AND
(
(@InState = 1
AND ADDR.State = 'CA')
OR
(@InState <> 1
AND ADDR.State <> 'CA')
)
When @Instate = 1
then these are the results;
ID State Status
1 CA A
3 CA A
6 CA A
When @Instate = 0
then you get this;
ID State Status
2 NY A
4 NJ A
5 FL A
7 ND A
Calculations in a WHERE
clause is going to kill your performance by making your query non SARGable
;
https://en.wikipedia.org/wiki/Sargable
Upvotes: 4
Reputation: 273
How about using IF ELSE
IF (@Instate=1)
BEGIN
SELECT *
FROM dbo.tAddresses ADDR
WHERE ADDR.Status = 'A'
AND ADDR.State ='CA'
END
ELSE
BEGIN
SELECT *
FROM dbo.tAddresses ADDR
WHERE ADDR.Status = 'A'
AND ADDR.State <>'CA'
END
I know its procedural not sure about the performance aspect. But another option.
Upvotes: 1
Reputation: 2020
This is the ugly one, but it works for me,
....
AND ADDR.State =
CASE WHEN @InState = 1 THEN 'CA' ElSE ADDR.State END
AND ADDR.State <>
CASE WHEN @InState = 0 THEN 'CA' ElSE ADDR.State END
Upvotes: 1