2011-02-14 4 views
1

サブクエリでNULLのフィルタが機能しないのはなぜですか? は、私には、例えば、許可された値のリストにNULLを追加することによって、正しい結果を得ることを望んだ:リスト内のNULLのフィルタ

SELECT  ERP_ServiceProcess.fiStatusNew, RMA.IdRMA 
FROM   ERP_ServiceProcess RIGHT OUTER JOIN 
         RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA 
WHERE (ERP_ServiceProcess.fiStatusNew IN (NULL, 1, 7, 8)) 
order by ERP_ServiceProcess.fiStatusNew 

これは間違った結果を与えるために、サブテーブルERP_ServiceProcessにレコードを持っていないRMA内のすべてのレコード(ERP_ServiceProcess .fiStatusNew IS NULL)が削除されます。

私は、正しい結果を得るために(遅い)クエリを、これを使用する必要があります。

SELECT  ERP_ServiceProcess.fiStatusNew, RMA.IdRMA 
FROM   ERP_ServiceProcess RIGHT OUTER JOIN 
         RMA ON ERP_ServiceProcess.fiRMA = RMA.IdRMA 
WHERE  (ERP_ServiceProcess.fiStatusNew IS NULL) 
OR (ERP_ServiceProcess.fiStatusNew IN (1, 7, 8)) 
order by ERP_ServiceProcess.fiStatusNew 

私はRIGHT OUTER JOINを使用して、私はサブクエリにNULLを追加しましたが、第二、遅いクエリを使用しなければならないのはなぜ?

ありがとうございます。

+0

あなたは 'SET ANSI_NULLS on'のとあなたの最初のクエリを試してみましたか? –

+0

@Adriy M:そうです。それは "間違った"結果を返す(NULLを落とした)。 –

+0

@Tim:もしかして、それがANSI_NULLS設定のNULL値を持つ関わらず行を省略しますか?それは価値がないことである、チェックする値ではないので、 –

答えて

2

それが操作

fiStatusNew = NULL OR fiStatusNew = 1 OR fiStatusNew = 7 OR fiStatusNew = 8

anything = NULL不明であるに等しいの束に拡大しますと、あなたが期待するように、それは動作しません。

ORを追加すると、IS NULLを追加すると特別な理由はありません。別の述語を使用すると、クエリによって統計情報が異なるアクセスパスを使用するように変更される可能性があります一致する行のワラントの数本が)

あなたがこれを使用すると、逆の操作で特定の世話をする必要がある理由の一つである

SELECT CASE NULL WHEN NULL THEN 'Yes' ELSE 'No' END /*Returns "No"*/ 

CASE操作で同じ動作を参照してください。リストにNULL値が含まれている場合は、空の結果セットが常に得られます。

fiStatusNew NOT IN (NULL, 1,2)

常にthree valued logicUnknownと評価さ

fiStatusNew<> NULL and fiStatusNew<> 1 and fiStatusNew<> 2

または

Unknown And True/False/Unknown And True/False/Unknown

に拡大します。

1

あなたは未テスト

ISNULL(ERP_ServiceProcess.fiStatusNew,0) IN (0, 1, 7, 8) 

を使用してみてくださいでしたが、第二のクエリよりも速くかもしれません。

+0

ヒントありがとうございます。はい、私はこれを行うことができます。しかし、最初のビューでは、それは私の2番目のクエリより速くはないようですが。最初のクエリ:<1秒、2回目(あなたの):> 4秒目。 –

+0

@Tim - このクエリは受け入れられません。インデックスではそれを満たすことはできません。 'fiStatusNew'にインデックスがある場合、あなたのクエリは*速くなります。 –

+0

@martin:まず、sargableを検索しなければなりませんでした。 http://stackoverflow.com/questions/799584/what-makes-a-sql-statement-sargable アドバイスをいただきありがとうございます。 'fiStatusNew'はすでに外部キーで、このカラムのインデックスを作成しても、2番目のクエリもFerminのクエリもパフォーマンスを変更しません。 –

0

'ERP_ServiceProcess.fiStatusNew = NULL'は、 'ERP_ServiceProcess.fiStatusNew IN(NULL)'と評価され、常にfalseです。 NULLはSQL Serverでは「不明」と定義され、「値なし」は定義されません。そのため、NULL = NULLまたはNULL = @var(*)は常にfalseと評価されます。 2つの未知数がある場合、それらが等しいかどうかを確認することはできません。 「NULL」のみが動作します。

(*)まあ、SQL Serverの、あなたはオフにANSI_NULLSを設定することができますが、それは、標準のSQLの動作ではありませんように、そのは本当にお勧めしません。

関連する問題