人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

PHP+PostgrSQLについて教えてください。

data1 に「キーワード」を含む行を取り出す場合はこのように書いているのですが
$result = pg_query(SELECT data1, data2, data3, FROM table WHERE data1 ~'キーワード'");

data1, data2, data3のどこで良いので「キーワード」を含む行を取り出す場合はどのように書くのでしょうか?

また、data1, data2, data3のどこでも良いので「キーワード1」と「キーワード2」の両方を含む場合、
また、data1, data2, data3のどこでも良いので「キーワード1」か「キーワード2」のどちらかを含む場合も教えてください。

よろしくお願いします。

●質問者: worldtravel
●カテゴリ:コンピュータ ウェブ制作
✍キーワード:PHP SELECT キーワード
○ 状態 :終了
└ 回答数 : 5/5件

▽最新の回答へ

1 ● llusall
●10ポイント

こちらでいかがでしょう?

>data1, data2, data3のどこでも良いので「キーワード1」と「キーワード2」の両方を含む場合

$sql = "SELECT data1, data2, data3 FROM table ";

$sql = $sql." WHERE (data1 like '%キーワード1%'";

$sql = $sql." OR     data2 like '%キーワード1%'";

$sql = $sql." OR     data3 like '%キーワード1%')";

$sql = $sql." OR    (data1 like '%キーワード2%'";

$sql = $sql." OR     data2 like '%キーワード2%'";

$sql = $sql." OR     data3 like '%キーワード2%')";

$result = pg_query($sql);



>data1, data2, data3のどこでも良いので「キーワード1」か「キーワード2」のどちらかを含む場合

$sql = "SELECT data1, data2, data3 FROM table ";

$sql = $sql." WHERE  data1 like '%キーワード1%'";

$sql = $sql." OR     data2 like '%キーワード1%'";

$sql = $sql." OR     data3 like '%キーワード1%'";

$sql = $sql." OR     data1 like '%キーワード2%'";

$sql = $sql." OR     data2 like '%キーワード2%'";

$sql = $sql." OR     data3 like '%キーワード2%'";

$result = pg_query($sql);

◎質問者からの返答

ありがとうございます

>data1, data2, data3のどこでも良いので「キーワード1」と「キーワード2」の両方を含む場合

$sql = "SELECT data1, data2, data3 FROM table ";

$sql = $sql." WHERE (data1 like '%キーワード1%'";

$sql = $sql." OR data2 like '%キーワード1%'";

$sql = $sql." OR data3 like '%キーワード1%')";

$sql = $sql." OR (data1 like '%キーワード2%'";

↑この行も「OR」で良いのですか?

$sql = $sql." OR data2 like '%キーワード2%'";

$sql = $sql." OR data3 like '%キーワード2%')";

$result = pg_query($sql);

>data1, data2, data3のどこでも良いので「キーワード1」か「キーワード2」のどちらかを含む場合

こちらはわかりました。

ちなみに

>data1, data2, data3のどこでも良いので「キーワード1」と「キーワード2」の両方を含む場合

というのは

data1.data2.data3 like '%キーワード1%|%キーワード2%'

というようなことはできないのでしょうか?

一つ一つ書くしかないのでしょうか?

サイトで使う際に複数のキーワードを入力でき、AND検索できるようにした際、

仮に5つキーワードを入力されると、上記のような感じで5回繰り返さなければならないのでしょうか?

?ばかりですがよろしくお願いします。


2 ● llusall
●10ポイント

再回答、失礼します。

たとえば、data1 の中のデータを考えた場合、

「aaaaキーワード1bbbbキーワード2cccc」

という文字列や、

「aaaaキーワード2bbbbキーワード1cccc」

という文字列の場合も対象にならなくてはなりませんよね。

ですので、

data1.data2.data3 like '%キーワード1%|%キーワード2%'

という風な記述では対応できないと思われます。

ちなみに、私、PHPもPostgrSQLも全く判らないのですが、

「|」という演算子?を使用した書き方は、無いと思います。

>仮に5つキーワードを入力されると、上記のような感じで5回繰り返さなければならないのでしょうか?

そうですね。面倒ですが、繰り返しになると思います。

なお、like演算子を使わないで済むのであれば、

data1 in ('キーワード1','キーワード2')

のように記述可能です。

これは、

   data1 = 'キーワード1'

OR data1 = 'キーワード2'

と同じです。

※「一致総数の取得と検索を同時に・・・」のご質問ですが、

SELECT COUNT(1) AS REC_CNT FROM table;

で、レコード件数を取得し、

SELECT data1, data2, data3, FROM table WHERE title Like '%キーワード%' LIMIT 20 OFFSET 0"

で、レコードセットを取得

という風に、面倒ですが2段階で取得する方法しかないと思います。

◎質問者からの返答

ありがとうございます

今本を見ながら勉強中なのですがPostgresならば「~」を使うと正規表現のパターンマッチが使えるので「~'キーワード1|キーワード2'」でできるそうです。

間違えでしたらどなたかご指摘下さい。

> ※「一致総数の取得と検索を同時に・・・」のご質問ですが、

面倒ですが2段階で取得する方法しかないと思います。

やはり面倒な感じなのですね


3 ● llusall
●0ポイント

再々回答で、すみません。汗

>↑この行も「OR」で良いのですか?

ご指摘のとおり、「AND」ですね。

申し訳ありませんでした。

◎質問者からの返答

いえいえ、念のための確認なのでお気になさらないで下さい。


4 ● Mook
●20ポイント

http://homepage2.nifty.com/sak/w_sak3/doc/sysbrd/sak3sql.htm

厳密な意味では難しいですが、むりやり文字列を連結するやり方でやるとすると、

$sql = 'SELECT data1 || data2 || data3 AS data123 FROM table '

$sql .= 'WHERE data123 like "%キーワード1%" '

$sql .= 'OR data123 like "%キーワード2%"'

というのもありかもしれません。

●文字列の連結は || です。

$sql .=$sql = $sql. と同じ意味です。

欠点は、data1 = "キー” data2 = "ワード” といった場合にも"キーワードにヒットしてしまう点です。

これを回避するには、連結時にキーワードには使われない文字をはさむ等で出来る気はします。

が、正道ではないかな。

◎質問者からの返答

ありがとうございます。

「||」で繋げられるんですね。

> $sql .= は $sql = $sql. と同じ意味

これはphpですよね。よく使ってます。

> data1 = "キー” data2 = "ワード” といった場合にも"キーワードにヒットしてしまう

確かにそうですね。

> これを回避するには、連結時にキーワードには使われない文字をはさむ等で出来る気はします。

> が、正道ではないかな。

検索が早ければ個人的には問題ない気もするのですが。。。


5 ●
●60ポイント ベストアンサー

このような検索には定石がありますので、それに従って素直に実装した方が良いと思います。

(語句の連結などで無理やり対応すると、完全一致の際などにINDEXが使われないなどの悪影響が出ます。)

また、私はPostgreSQLには詳しくないのですが、DBの移行の可能性なども考慮し、独自関数に頼らず、ややこしい処理はプログラム(PHP)側で行い、SQLは一般的なものにしておいた方が良いでしょう。

簡単なサンプルを書いてみましたので、確認してみてください。

キーワードの数に依存せずに、適切なSQLを生成できます。

(ソースの見通しをよくするためにpg_escape_stringなどは行っておりませんので、実際に使う際には適切な前処理をほどこしたデータのみDB検索に使うようにしてください。)

<?php
/*
$_POST["search_words"]に半角スペース区切りの文字が入っていることを想定
以下では代わりに$post_search_wordsという変数を用いる
*/
$post_search_words = "abc def ghi";
$vague_flag = 0; // $vague_flagで完全一致か曖昧検索かを分ける ( 0:完全,1:曖昧 )
$andor_flag = 0; // $andor_flagでAND検索かOR検索かを分ける ( 0:AND,1:OR )
/*
preg_splitを用い、検索語句を半角スペースごとに分解
$keywords配列に代入
*/
$keywords = preg_split("/\s/",$post_search_words);
// $andor_flagの値によってANDを使うか、ORを使うかを分ける
if ($andor_flag == 0 ){
$andor = "AND ";
} else if ($andor_flag == 1 ){
$andor = "OR ";
} else {
print "エラーです。";
exit;
}
// $vague_flagの値によって完全一致か曖昧検索かを分ける
switch ($vague_flag) {
case 0:
$sql = "SELECT data1, data2, data3 FROM table WHERE ";
for ($i=0;$i<count($keywords)-1;$i++){
$sql .= "(data1 = '" . $keywords[$i] . "' OR data2 = '" . $keywords[$i] . "' OR data3 = '" . $keywords[$i] . "') " . $andor;
}
$sql .= "(data1 = '" . $keywords[count($keywords)-1] . "' OR data2 = '" . $keywords[count($keywords)-1] . "' OR data3 = '" . $keywords[count($keywords)-1] . "')";
print $sql;
break;
case 1:
$sql = "SELECT data1, data2, data3 FROM table WHERE ";
for ($i=0;$i<count($keywords)-1;$i++){
$sql .= "(data1 LIKE '%" . $keywords[$i] . "%' OR data2 LIKE '%" . $keywords[$i] . "%' OR data3 LIKE '%" . $keywords[$i] . "%') " . $andor;
}
$sql .= "(data1 LIKE '%" . $keywords[count($keywords)-1] . "%' OR data2 LIKE '%" . $keywords[count($keywords)-1] . "%' OR data3 LIKE '%" . $keywords[count($keywords)-1] . "%')";
print $sql;
break;
}
?>

$vague_flag、$andor_flagの値を変更することで、出力されるSQLが変わりますので、確認してみてください。

これらのflagは画面上にcheckboxを設置し、その状態によって値を決めると良いと思います。

[参考URL]

参考になれば幸いです。

◎質問者からの返答

なるほど!!

こういうやり方が「定石」なのですね。

phpでキーワード数分繰り返してSQLを作るのですね。

こういう「定石」が知りたかったのです。

ありがとうございました。

関連質問


●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ