今使っている処理系はSQL Server 2008ですが、一般的なRDBについての回答でもSQL Serverに限った回答でもかまいません。
レコード検索画面を作るとき、各検索条件が指定されていればそれで絞り込むという動作をさせたいです。よくある要求だと思います。
このとき、検索条件が指定されていればWHERE句にAND式を追加するという動的組み立てをどうしてもせざるを得ません。
動的組み立てを避けて AND(@cond IS NULL OR coldate = @cond)
のような式を書くと実行コストが跳ね上がりますので。
かといって、各条件が指定されているかどうかで分岐してそれぞれカスタマイズされたクエリが呼ばれるようにしようとすると組み合わせ爆発です。
このような場合、どう問い合わせを書くのがいいやり方なのでしょう?
下記の式は左側から評価されるので、途中でfalseになればスキップしますし、想像されているほどコストがかかるものではありません。
WHERE COLA='A' AND COLB='B' COLC='C' AND...
下記サイトの正規化の手順を参考にしてください。
http://jibun.atmarkit.co.jp/lskill01/rensai/db/07/01.html
カラム数がやたら多いテーブルよりは、複数テーブルに分割した方がメンテナンス性が高くなりますし、selectで表示するカラムを明示してやることで、結合のコストは帳消しにできます。
正規化を行っていれば、NULL値を持つような従属カラムは存在しなくなるはずです。(そのようなレコードをinsertする必要がないから)
これで、検索コストやデータ容量の節約になります。
なるほど垂直分割……
参照クエリの姿としては、
FROM メインテーブル
LEFT JOIN サブテーブルAを絞り込むかもしれないストアド関数 @a USING(record_id)
LEFT JOIN サブテーブルBを絞り込むかもしれないストアド関数 @b USING(record_id)
LEFT JOIN サブテーブルCを絞り込むかもしれないストアド関数 @c USING(record_id)
...
のようなものをイメージすればいいのですかね。
ストアド関数は、引数がNULLならテーブル内容を単にSELECT、引数がNON-NULLならSELECT-WHEREの結果を返すものとして。
この手法、ちょっと掘り下げてみたいです。
パターン名なんかはついていませんかね?
ISやORを使うのはコストに跳ね返ってきますね。
2013/03/11 11:59:28しかし、検索コストを考えてDB設計を見直すしか方法はありません。
そもそも、COLBが検索条件になりかつNULLを許しているというのは、DB設計上の問題があります。
あ、失礼。COLBはNULLを許していません。
2013/03/11 12:13:42@bに検索条件が指定されたなかった、ですから
WHERE COLA=@a AND (@b IS NULL OR COLB=@b) AND COLC=@c AND...
ですね。
ともあれ、そのDB設計の見直しですが、どういうのがいいやり方ですか? というのが今回の質問です。問題があることは明らかですので。