SQLのCASE演算子で条件の有無を判断して必要な場合のみWHERE句の条件に含める

スポンサーリンク

SQLでテーブルの情報を抽出(SELECT)する際に、特定の場合だけWHERE句で条件を指定したい場合があります。

例えば、抽出条件(値)が指定されている場合は、WHERE句の条件式に含めたいけど、抽出条件(値)が指定されていない場合は、条件式に含めたくない…。
プログラムからSQLを作成する際に、if文で条件分岐をして

のように、抽出条件の有無によって生成するSQLを変更すればできるけど…。
できれば、SQLの中で抽出条件の有無を判断して、プログラム側での条件分岐はしたくない…。

そんな時は、SQLのCASE演算子を使えば、プログラム側で条件の分岐をしなくても、値のある時だけWHERE句の条件に含めることができます。

使用するテーブル

ここでは例として、会員の情報を管理するテーブルがあるとします。
会員テーブルには [会員コード] と [会員氏名] と [性別コード] の3つのカラム(列)があるとします。

テーブル名

テーブル名 テーブルID
会員テーブル TBL_MEMBER

テーブルの列定義

No カラム名 カラムID
1 会員ID MEMBER_ID
2 会員氏名 MEMBER_NAME
3 性別コード SX_CODE

テーブルに登録されているデータ

会員ID 会員氏名 性別コード
001 会員 一郎 1
002 会員 二郎 1
003 会員 一子 2
004 会員 三郎 1
005 会員 二子 2
006 会員 三子 2

※ 性別コード「1:男性」「2:女性」

会員情報の抽出を行う画面

画面はシンプルに以下のような感じで

会員検索
検索条件
氏名
性別

会員の「氏名」はテキストボックスに直接入力「性別」はドロップダウンリストから選択する形式で検索条件を指定できる仕様としておきます。

プログラム側でSQLのWHERE句を生成する場合

プログラム側で抽出条件の有無よってSQLを分岐すると

C#でのサンプル

こんな感じでしょうか。
if文を使って分岐すれば、氏名と性別の条件指定の形式によって
氏名のみ条件の指定があれば

性別のみ条件の指定があれば

氏名と性別の両方の条件の指定があれば

氏名と性別の両方の条件の指定がなければ

の異なるSQLが生成され、それぞれの結果が取得されるので問題ないんですが、if文を記述するのが面倒なので、これをif文を使わずに同様の結果が取得できるようにします。

SQLのみでWHERE句を生成する場合

C#でのサンプル

WHERE句にCASEを使って条件の有無によって条件を分岐しています。
ポイントは、条件の指定がない場合(空文字列の場合)のELSE以降の部分
ELSE MEMBER_NAME END
ELSE SX_CODE END
条件を照合する列に対して照合する値に条件を照合する列を指定している箇所です。
WHERE句に「WHERE 0 = 0」と記述すれば、条件を指定していない場合と同様の結果が得られるのと同様に
「条件を照合する列」に「条件を照合する列」を指定するということは、「条件を照合する列」=「条件を照合する列」です。
「条件を照合する列」を0に置き換えると 0 = 0 になるので、結果として条件を指定していない時と同様の結果になります。
プログラムからSQLを作成する方法とは別に、SQLのみで同様の結果を得るようにするなら以下のようになります。

SQLServer(T-SQL)でのサンプル

上記の例では、会員氏名の条件を「=」(完全一致)で照合していますが、これだと使いにくいので、「LIKE」(部分一致)で検索できるように変更してみます。
「LIKE」を使う場合でも、基本的には「=」と同様です。
「会員氏名 = ‘抽出条件の値’」となっている箇所を「会員氏名 LIKE ‘%抽出条件の値%’」に変更するだけです。

実行して得られる結果表

上記のSQLを実行すると、以下のような結果表を取得することができます。

会員ID 氏名 性別
004 会員 三郎 男性

ちなみに、上記の方法でデータを抽出する際に、対象の列(会員氏名、性別コード)の登録値がNULLになっている場合は、正しくデータを取得することができないので、NULLが登録される可能性がある列と照合を行う場合は
SQLServerならISNULL関数を使って

MySQLならIFNULL関数を使って

としてNULLを”(空文字列)に変換する必要があります。
ISNULL、IFNULLの代わりにここでもCASE演算子を使って

と記述することもできます。

今回ご紹介した記事は、別になくてもプログラムを記述する際には困るものではありませんが、個人的にはプログラムでif分岐をするよりもソースがシンプルになる+DBの関数オブジェクトとして作成する際も簡単なのでよく使っています。

SQLのCASE演算子はとても便利な演算子なので、皆さんもいろいろと使ってみて、スマートなSQLを書いてみてください。