2011-12-23 23 views
4

は明らか "x IS NULL"と "NOT(x IS NOT NULL)"の違いは何ですか?

SELECT "users".* FROM "users" WHERE ("users"."deleted_at" IS NULL) 

SELECT "users".* FROM "users" WHERE (NOT ("users"."deleted_at" IS NOT NULL)) 

間PostgreSQLの実行、パフォーマンス、またはロジックに有意差が誰だろう(手で書かれている場合、最初の式は、私が書くでしょう一つであり、意図的に二重否定を書くか?)。しかし、この場合には、私は一種のようにのように、動的に両方のバージョンを作成するためにルビーのARELライブラリを使用しています:

def generate_query(search_terms, negated=false, users=User) 
    where_clause = arel_for_one_of_many_possible_queries(search_terms) 
    where_clause = where_clause.not if negated 
    users.where(where_clause) 
end 

そして、"deleted" SEARCH_TERMため、where_clausearel_table[:deleted_at].not_eq(nil)になりますが、他のSEARCH_TERMSのためにそれができます複合句や副選択句を含むさまざまな句。 .notを最後に追加すると、arelは常に2番目の形式のSQLを生成します。私私のNULLチェックを特別なケースで最初のフォームを生成し、場合によっては.eqまたは.not_eqを手動で生成することができますが、私はコードをより冗長にする前にそれを行うことにいくつか明確な利点があります。

+1

2つのWHERE節はまったく同じ結果をもたらします。機能的な違いはありません。ただし、クエリプランナでは、それを使用する必要がある場合は、おそらく式にフィッティングインデックスを使用することはできません。 –

答えて

7

EXPLAINを使用してください。

私はこのクエリーリライタがこれを最適化すると思いますが、この例ではソースコードをチェックしませんでした。

編集:私は間違っていましたが、これはまったく最適化されていません。 ( "users"。 "deleted_at"がNULL)は、インデックスを使用することができます(NOT( "users"。 "deleted_at" IS NOT NULL))条件でシーケンシャルディスクスキャンが実行されます。

+0

明らかに 'explain'をチェックしなければなりません!ありがとう。しかし、物事を絶対的に明確にするためには、両者の論理的な違いはありません。私はときどき不幸な驚きにつながるNULL等価を扱うための正確なSQL関係代数ルールが何であるか忘れています。 –

+0

FWIW、postgresql 8.4.9のクエリーリライタは、私のためにこれを書き換えているようではありません。だから私は生産データでそれをテストして、パフォーマンスに大きな違いがあるかどうかを確認する必要があります。 –

+0

2つのクエリプランの違いを教えてください。 –