中学受験専門 理科総合研究所 −理総研−

フロントページへ
Name:
Pass:
RSS
: ユーザー登録はコチラ :
左 理総研:技術情報と開発メモ 右

001:MySQLのカラムから、And,Orによる文字列検索

対象言語:PHP / MySQL
PHP 5.0 MySQL WHERE LIKE AND OR 文字列 検索 アンド オア カラム データベース

ANDOR
昔はありましたよね、検索サイトのANDとかORとか。理総研ではLIKEを使ったこのアンドとオアの文字列検索が問題作成時に必要となったので実装しています。テーマは、
・AND / OR どちらのオプションでも
・入力された検索語が0個でも1個でも複数でも
・PHP側の処理を極端に減らして
その上で<SQL文を1行だけ発行して処理を増やさない>です。検索語が1つの場合はANDでもORでも同じ検索結果が得られないといけません。
本家MYSQLサイトでも「OR で結合された 2 つの異なるキーを使用した検索は、まだ最適化されていません」(@3.6.7. 2 つのキーを使用した検索)とあったり、UNION構文でSELECTを繋げたりとあったり、ORの場合はIN演算子で代用したりとありましたが、いや、1行にこだわりたい。 入力されたデータを処理(空白・タグ等の除去とか)した後、不特定な数の検索語をWHERE句内で連結するのですが、この連結(特にORの場合)がなかなか悩みました。

	//あらかじめPOSTされたデータを処理(空白・タグ等の除去)して配列にしておく。

	$kensaku_words = array("検索したい文字列たち");
	$kensaku_op = "検索オプション(AND / OR)";
	
	if ($kensaku_op === "AND") {
	 $operand = 1;
	} else {
	 $operand = 0;
	}

  • 5行目:AND検索ならオペランドを「1」(というか0以外なら何でもOK)7行目:OR検索の時にオペランドを「0」にします。WHERE句の1番初めに付けることで、foreachによる複数ある検索語の連結を容易にしています。 なぜOR検索の時にオペランドを0にするのか・・・説明が大変そうなので端折ります。

	$where = "WHERE " . $operand;
	
	// ここのWHEREのすぐ後ろに空白が付いているのをお忘れ無く!
	
	foreach ($kensaku_words as $word) {
	  $where .= " " . $kensaku_op . " `テーブル` LIKE '%{$word}%'";
	}

  • 「.= 」でWHERE句を連結していきます。常に先頭に空白を付け足すことをお忘れ無く!
    あと、オプションでやってきたANDとORの文字列もそのまま利用して処理を分けない設計にします。特にLIKEである必要がないなら、`検索したいカラム` = '{$word}'で。

	$sql = "SELECT `id` FROM '検索対象のカラム' {$where}";
	$result = mysql_query($sql,$link) or die(mysql_error());
	
	while ($rec = mysql_fetch_assoc($result)) {
	 $kensaku_id_array[] = $rec['id'];
	}

  • `id`部分は何でも良いですが、ここではインデックスとなるカラムを指定して、その値を配列$kensaku_id_arrayに格納し、後に利用するようにしています。 データが大量にある場合は配列にしてPHPで処理するよりも、$resultの結果をそのまま利用した方が良いです。
著者 You Mizuguchi
© 2011 System-iDO IT Devisers