複数フィールドに複数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%'
ご質問にあるレコードを見ると、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
確実に効率は悪いのですが、a_nameとa_tagを文字列結合して、結合文字列をlikeで検索したらどうですか。
もちろん文字列結合時にはnullを考慮しないといけませんが。
concatですか?
質問にもありますが
http://okwave.jp/qa/q2634613.html
で『素人の遊び』と書かれていれば、では効率のいい方法があるのかな・・・と思いました。
素人ですが。
商品名にユーザーがタグをつけ、どちらでも検索できるようにしたいのです。
動く方法でなく、テーブル設計も含め効率のいい方法のアドバイスを希望します。
できれば、サンプルまであると助かります。
コメントありがとうございます。
FullTextインデックスは初めて知りました。
勉強になります。
ご質問の主旨を誤解していたかもしれないので、あらたに回答を起こしました。
1つの商品(アイテム)に対して複数のタグを入力・登録・検索したいというご要望であれば、次のように正規化(1つ1つのタグに分解)を行い、テーブルを分割するというのが基本です。インデックスを作成したとしてもlike演算子を使うのは効率が悪くなるので、A_idでリレーションを張ります。
A_id | Name |
---|---|
1 | 白州 |
2 | 山崎 |
3 | 余市 |
4 | 宮城峡 |
B_id | A_id | Tag |
---|---|---|
1 | 1 | サントリー |
2 | 1 | 長野 |
3 | 2 | サントリー |
4 | 2 | 大阪 |
5 | 3 | ニッカ |
6 | 3 | 北海道 |
7 | 4 | ニッカ |
8 | 4 | 仙台 |
タグを検索するための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
何度もありがとうございます。
今の環境では、MySQL+sennaは導入が難しいことがわかりました。
お手頃のVPSがあったので、少しずつ挑戦してみたいと思います。
http://dream.jp/vps/
日本語の全文検索は遅いハズです。
MySQL SennaでNGRAMかmecabを使うと速いです。
効率という点ではindexの貼り方も確か意味が合ったはず。
http://labs.unoh.net/2007/06/mysql5.html
と思いましたがMySQL5からは適時、indexを組み合わせて使ってくれるようです。
極端な話し全てのカラムにindexを貼っておけばOK。
心配ならEXPLAINを使って検証してみてください。
今の環境ではMySQL+Sennaは難しいので、とりあえずインデックスを貼りまくりで一時をしのごうと思います。
そのうちぼちぼちとSQL+Sennaにも挑戦したいと思います。
参考になるページを紹介して頂きありがとうございました。
$key1 と $key2 の関係はAND条件なのかOR条件なのか分かりませんが、いずれにしても
2012/03/05 16:54:04・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はユーザーが入力するので
ユーザーが入力した値をそのままカラムに格納することは、普通ありません。
回答欄に示したリンク先を参考にしてください。
何度も恐縮です。
2012/03/05 18:22:50> 検索可能なはずです。
この質問の場合andとかorとか関係なく、また可能な方法でなく、『複数フィールドに複数key検索』に関して効率のいい方法のアドバイスを求めています。
サンプルを挙げやすいと思い例を乗せましたが、テーブルを簡略化したことで誤解を生んでいるようです。
一つのフィールドがタグが例だったので、設計に問題アリと思われたのですね。
例ではタグを挙げましたが、コメント文章でも構いません。
現在、FullTextインデックスについて調べています。