2016-06-15 9 views
0

宣言された変数に基づいて、where句でnot equalとequalを切り替えることはできますか?TSQLが等しいかどうかWHERE句の条件付き

たとえば、変数@InStateがtrueに設定されている場合、状態が「CA」のすべてのアドレスを返します。偽の場合は、状態が<>「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」と同じではありません。

+0

[Conditional where節がSql Serverにありますか?](http://stackoverflow.com/questions/18629132/conditional-where-clause-in-sql-server) –

答えて

3

私はWHERE句にCASEの記述を避けて、このようなものに行きます。

試験データ;

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これを取得すると、 WHERE句の

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

計算はSARGableクエリが非作ることによって、あなたのパフォーマンスを殺すために起こっています。

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

+0

ありがとうございました。私はそれを若干修正する必要がありましたが、それは状態のアドレスの外を表示するために得るためです。 '@InState <> 1'を' @InState <> 1 AND ADDR.State <> 'CA')に変更しました。 – Wellspring

+0

ええ、気がついたことに、それをむしろ<>に変更する必要があると思いますより=私の更新された答えを見てください。 –

+0

うん、ありがとう。それは私のコメントのタイプミスでした。修正しました。 – Wellspring

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 
+0

これはすべての結果を抑制すると思いますが、最後の2つを角かっこで囲み、それらの間にORを使用したいのですか? –

+0

あなたは正しいです。私は両方の場合をテストするために '='を使用しました。しかし、それは等しくないときに問題があります。これはOKであるはずです... @InState = 0の場合THEN 'CA' Else '何か存在しません' END – user1111

1

ない句が、私はそれが検索引数可能

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 
だと思います
+0

これは確かにADDRのすべてを返します。これらの内部結合の両方を行うことで、実際には何も除外していません。確かに@RichBenner –

+0

?なぜあなたはそれをテストしないのですか? – Paparazzi

+0

@instateが1または0に設定されているかどうかにかかわらず、すべての結果を抑制しています。 –

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 

私はその手順上、パフォーマンス面についてはわかっていません。しかし別の選択肢。

+1

解決策を共有してくれたBijuに感謝します。私はまだSQLについて学んでいるので、同じ問題を解決する方法は複数あります。 – Wellspring