前文
WHERE (Col1 = 1 OR Col2 =1)
上記のようなクエリは以下のように正規化(?)することができる。
WHERE 1 IN (Col1, Col2)
少しだけ単純になる。「仕様変更に強い」かは置いといて。
面白いのは結果として、所謂 ヨーダ記法 になること。
ヨーダ記法の是非はここでは論じない。それよりも問題はインデックスが効くのかこれ? という素朴な疑問。クエリである以上。
ざっとぐぐったところ答えが見つからなかった(クエリでヨーダ記法なんて普通書かないだろうし)ので確認した次第。
環境
SQLServer | SQLCMD |
---|---|
2017 | 14.0.1000.169 |
設定はデフォルト。 |
結論
効く。
そもそも IN句とは、OR で連結した等式の シンタックスシュガー。
WHERE Col1 IN (1, 2)
よく IN句の説明で、上記のクエリは以下のクエリと同じ、みたいな説明を見かける。
WHERE (Col1 = 1 OR Col1 = 2)
同じも何も、IN句は内部的には後者のように展開される。IN句を直接解釈できる DB なんて自分が知る限り存在しない。(多分)
IN句の括弧の中身が SELECT文のケースを除き、値がリストとして列挙されている場合、機械的に OR で連結した等式に置き換えることができるから。
そうすれば後は通常のクエリとして処理することができるし、わざわざ IN句専用の実行プランを実装する必要はない。
余談ついでに。
長年三項演算子(条件演算子)的な機能が求められていた SQLServer。
よく掲示板でも、SQLServer で三項演算子みたいなことを行いたい場合は? といった質問に対して、CASE式で代用してくださいというやり取りが定番だった。
それが 2012 から IIF関数 が追加された。でもこれって恐らく内部的には CASE式に展開されているんだよね。つまり、CASE式のシンタックスシュガー。
システムとして用意されたのは有難いけど。
で、話をヨーダ記法に戻す。実行プランを確認したら以下だった。
因みに上記は Col1
が主キーだけど、キーが張られていない場合は以下だった。
OR で連結した等式に置き換えるだけではなく、列名を左に置き換てくれるんだね。一種の正規化処理といえるのかな。
つまり場合によっては、
WHERE 1 IN (Col1, Col2)
と書いたところで、結局一周周って以下に展開されるというね。
WHERE (Col1 = 1 OR Col2 =1)
主キーの有無によって展開のされ方が微妙に異なるのは興味深い。因みに Oracle でも確認したところ同様だった。恐らく大抵の DB で同じと思われ。
May the Force be with you.