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

php5.2+MySQL5のlike条件に関する質問です。
複数フィールドに複数keyで検索を行う場合、どのような方法が効率がいいでしょうか?
以下テーブルのA_nameでもA_tagでも検索したいのです。
http://okwave.jp/qa/q2634613.html
も見ましたが、『(キー、情報区分、情報)という構成』の意味がわかりません。
複数フィールドで検索しないといけないテーブル設計が悪いということでしょうか?
複数フィールドがいけないのであれば、検索専用のフィールドA_searchを設け『1 白州 サントリー、長野』を作ろうかと思いましたがカッコよくない気がします。
下記コードにアドバイスいただけないでしょうか?
よろしくお願いします。

検索キー
$key1 = "サントリー";
$key2 = "長野";

table_A(pkey A_id)
A_id, A_name, A_Tag
1, 白州, サントリー、長野
2, 山崎, サントリー、大阪
3, 余市, ニッカ、北海道
4, 宮城峡, ニッカ、仙台

select * from table_A where A_name like '%$key1%' and A_name like '%$key2%' and A_Tag like '%$key1%' and A_Tag like '%$key2%'

●質問者: seadwell
●カテゴリ:ウェブ制作
○ 状態 :終了
└ 回答数 : 4/4件

▽最新の回答へ

1 ● oil999
●50ポイント

ご質問にあるレコードを見ると、A_nameカラムに入っているのは$key1のみで、A_Tagカラムに入っているのは$key2のように見受けられます。
したがってSQL文は次のようになるのではありませんか。

select * from table_A where A_name like '%{$key1}%' and A_Tag like '%{$key2}%';

もしA_nameカラムには$key1も$key2も入っている、A_Tagカラムには$key1も$key2も入っているという状況でしたら、それはテーブルの設計が悪いです。

データベース構築では、概念設計、論理設計、物理設計の3段階の手順を踏んで設計を行いますが、論理設計の段階できちんと正規化ができていないといけません。まず、A_nameとA_Tagの役割を明確に分解する第1正規形ができていないといけません。

初めてのデータベース設計

http://gihyo.jp/dev/feature/01/database/0001

第1正規形

http://design.first-database.com/1nf.html


seadwellさんのコメント
検索キーとレコード例が悪かったですね。 とにかく、A_nameも検索対象にしたいのです。 以下の例で、アドバイスお願いします。 検索キー $key1 = "山崎"; $key2 = "2012"; table_A(pkey A_id) A_id, A_name, A_Tag 1, 白州, サントリー、長野 2, 山崎, サントリー、大阪 3, 白州 シェリー, 2012、限定 4, 山崎 シェリー, 2012、限定 5, 山崎 シェリー, 2010、限定

seadwellさんのコメント
読み返すと質問が舌足らずですね。追記です。 A_tagはユーザーが入力するので、A_nameと被る可能性はあります。

oil999さんのコメント
$key1 と $key2 の関係はAND条件なのかOR条件なのか分かりませんが、いずれにしても ・AND条件なら select * from table_A where A_name like '%{$key1}%' and A_Tag like '%{$key2}%'; ・OR条件なら select * from table_A where A_name like '%{$key1}%' or A_Tag like '%{$key2}%'; で検索可能なはずです。 >A_tagはユーザーが入力するので ユーザーが入力した値をそのままカラムに格納することは、普通ありません。 回答欄に示したリンク先を参考にしてください。

seadwellさんのコメント
何度も恐縮です。 > 検索可能なはずです。 この質問の場合andとかorとか関係なく、また可能な方法でなく、『複数フィールドに複数key検索』に関して効率のいい方法のアドバイスを求めています。 サンプルを挙げやすいと思い例を乗せましたが、テーブルを簡略化したことで誤解を生んでいるようです。 一つのフィールドがタグが例だったので、設計に問題アリと思われたのですね。 例ではタグを挙げましたが、コメント文章でも構いません。 現在、FullTextインデックスについて調べています。

2 ● くろふね
●50ポイント

確実に効率は悪いのですが、a_nameとa_tagを文字列結合して、結合文字列をlikeで検索したらどうですか。

もちろん文字列結合時にはnullを考慮しないといけませんが。


seadwellさんのコメント
concatですか? 質問にもありますが http://okwave.jp/qa/q2634613.html で『素人の遊び』と書かれていれば、では効率のいい方法があるのかな・・・と思いました。 素人ですが。 商品名にユーザーがタグをつけ、どちらでも検索できるようにしたいのです。 動く方法でなく、テーブル設計も含め効率のいい方法のアドバイスを希望します。 できれば、サンプルまであると助かります。

seadwellさんのコメント
コメントありがとうございます。 FullTextインデックスは初めて知りました。 勉強になります。

3 ● oil999
●50ポイント

ご質問の主旨を誤解していたかもしれないので、あらたに回答を起こしました。

1つの商品(アイテム)に対して複数のタグを入力・登録・検索したいというご要望であれば、次のように正規化(1つ1つのタグに分解)を行い、テーブルを分割するというのが基本です。インデックスを作成したとしてもlike演算子を使うのは効率が悪くなるので、A_idでリレーションを張ります。

table_A(pkey A_id)

A_idName
1白州
2山崎
3余市
4宮城峡

table_B(pkey B_id, skey A_id)

B_idA_idTag
11サントリー
21長野
32サントリー
42大阪
53ニッカ
63北海道
74ニッカ
84仙台

タグを検索するためのSQL文は次のようになります。

SELECT * FROM table_B JOIN table_A ON tableB.A_id=tableB.A_id WHERE tableB.Tag='{$key1}' OR tableB.Tag='{$key2}';

もしタグを分割しないでそのまま1つのカラム(A_Tag)に登録して検索を行いたいということであれば、日本語全文検索技術を導入する必要があります。(UTF-8を使っていればFullTextインデックスは適用可能ですが、4文字以下は検索されないという制約があります)
MySQLであれば、sennaを導入することが多いです。
http://qwik.jp/senna/FrontPageJ.html


seadwellさんのコメント
何度もありがとうございます。 今の環境では、MySQL+sennaは導入が難しいことがわかりました。 お手頃のVPSがあったので、少しずつ挑戦してみたいと思います。 http://dream.jp/vps/

4 ● もすぴー
●50ポイント

日本語の全文検索は遅いハズです。
MySQL SennaでNGRAMかmecabを使うと速いです。

効率という点ではindexの貼り方も確か意味が合ったはず。

http://labs.unoh.net/2007/06/mysql5.html

と思いましたがMySQL5からは適時、indexを組み合わせて使ってくれるようです。
極端な話し全てのカラムにindexを貼っておけばOK。

心配ならEXPLAINを使って検証してみてください。


seadwellさんのコメント
今の環境ではMySQL+Sennaは難しいので、とりあえずインデックスを貼りまくりで一時をしのごうと思います。 そのうちぼちぼちとSQL+Sennaにも挑戦したいと思います。 参考になるページを紹介して頂きありがとうございました。
関連質問

●質問をもっと探す●



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