Where子句中的TSQL等于或不等于条件

时间:2016-06-15 14:23:30

标签: sql sql-server tsql

基于声明的变量,是否可以在where子句中切换不等于和等于?

例如,如果变量@InState设置为true,则返回状态等于' CA'的所有地址,如果为false,则返回状态为<>的所有地址。 ' CA'

代码:

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

上面代码中的ELSE返回包括' CA'在内的每个州。我需要返回其他所有状态,而不是等于CA'

4 个答案:

答案 0 :(得分:3)

我会尝试避免CASE条款中的WHERE语句,并尝试这样的事情;

测试数据;

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

查询

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

@Instate = 1时,这些就是结果;

ID  State   Status
1   CA      A
3   CA      A
6   CA      A

@Instate = 0时,你得到了这个;

ID  State   Status
2   NY      A
4   NJ      A
5   FL      A
7   ND      A

WHERE子句中的计算会使您的查询非SARGable,从而导致您的表现下降;

https://en.wikipedia.org/wiki/Sargable

答案 1 :(得分:1)

这是丑陋的,但它对我有用,

...

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

答案 2 :(得分:1)

不是where子句但我认为它是可以攻击的

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

答案 3 :(得分:1)

如何使用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

我知道它的程序性能不确定。但另一种选择。