自身の任意のwhere節の条件を含む場合は、null試験)
-
13-09-2019 - |
質問
たいへの効率的にチェックした場合に何らかの列に一致する <condition A=""> と一致しない <condition B="">の条件は任意である。
Oracle、この ほとんど 作品:
select count(*) from dual
where exists (
select * from people
where (<condition A>)
and not (<condition B>)
);
-- returns zero if all rows that match <condition A> also match <condition B>
-- (well, almost)
問題は、恐ろしいでnull値です。ょう <condition A=""> は 名='アーロン' や <condition B=""> は 年齢=21.クエリを正確に識別すAaronsがするものではなく、21が失敗した場合に識別すAarons者はnullになります。
ここで正解がテーブルの何百万の記録できるまでについては、
select (
select count(*) from people
where (<condition A>)
) - (
select count(*) from people
where (<condition A>)
and (<condition B>)
) from dual;
-- returns zero if all rows that match <condition A> also match <condition B>
-- (correct, but it is s l o w...)
残念ながら二つの条件は、任意の複雑な変化は、一般的にの後に続きが出来るのかって?ては、原則として発行体から対価を用の永続化の枠組みからユーザを検索しの状態に保つよう努めて指数とユーザーの皆さまに多くの時間が経つにつれ、大きなテーブルスキャン(その最初のクエリの"が存在する条項"の方がはるかに高速にでき止めてできるようにするためのlibsoupお一マッチングの記録という二つの別々のスキャン).
する方法を教えてくださいここにしなければならなかっfutzingはnull?
解決
あなたはidフィールドを持っている場合は、試してみてください。
SELECT COUNT(*)デュアルから (どこに存在します 人から*を選択 ここで、(指揮のA) そして、(ここで、(指揮b)は、人々からIDを選択)していないzzz.id );
他のヒント
と仮定しておーブルに主キー id
, の一つと考:
select count(*)
from people p1
left join people p2
on (p1.id = p2.id
and (p2.<condition A>)
and (p2.<contition B>))
where p1.<condition A>
and p2.id IS NULL
必要はありません。一 簡単な 前処理の条件(prefacing各カラム名 p1.
または p2.
として適切なものとするより正確に否定条件の NULL
問題のきものもあります。
LEFT JOIN sometable ON whatever WHERE ... AND sometable.id IS NULL
人気の表現方法"、ある対応する記録 sometable
と満足の whatever
制約ようなので期待は良いことでエンジンや調整を最適化する音などのご指す"ことである。
すべてのNULL可能列に有効なことがないようにしてくださいダミーの値を思い付くことができるなら、あなたはこのような何かを行うことができます:
select count(*) from dual
where exists (
select * from (
select NVL(name, 'No Name') name, NVL(age, -1) age from people
)
where (<condition A>)
and not (<condition B>)
);
あなたはおそらくそれらの式にファンクション索引を作成したいと思う。
これは確かに、実行時に条件によって解析しNVL式を持つ列名を置き換えるためにしようとするよりも簡単であり、それは同じ結果を持っている必要があります。
私はあなたの条件がある場合は、の完全にの任意何かできることはないと思います。いくつかのルールに基づいて、いくつかの点で条件「再書き込み」に、それは可能ですか?
私はあなたがこれを行う場合と信じています
... where not (age = 21) ....
に内部的に変換されます:
... where (age != 21) ...
それはNULL値と一致しないため、あなたは右、あまりにもいくつかのレコードを取得する?
しかし、あなたがこれを行う場合:
... where not (age = 21 and age is not null) ....
に内部的に変換されます:
... where (age != 21 or age is null) ....
そして、あなたが期待される結果が得られます。 (右?)
だから、(...または、xがnullの場合)のいずれかの形で、ヌルテストを含めるためにあなたの条件ですべての比較を強制するか、(...、xがnullではない)ことができますか?
一つの解決策は、を任意のヌルを取り除くためにある比較のパラメータの範囲内は最初、つまり、値に文字列を追加するか、その列の不可能な値にnullを交換してください。最初の例:
select x, y
from foo
join bar on bar.a||'x' = foo.a||'x' /* Replace "=" with "<>" for opposite result */
;
NULLを交換ます:
select x, y
from foo
join bar on nvl(bar.a, 'x') = nvl(foo.a, 'x') -- Ditto
;
あなたは、交換価値は、それが置き換えられ、列と同じデータ型であることを確認する必要があるため、さて、2番目のオプションは、(NVLはそのようなビット愚かである)(少なくともOracleの9.2で)難しいです、そして、それはだこと列のデータ型の精度外の値は、(例えば、9999
用number(3)
)が、それはインデックスで作業することが可能かもしれません。カラムが既に最大精度/長さを使用している場合もちろん、これは不可能である。