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%'

回答の条件
  • 1人5回まで
  • 13歳以上
  • 登録:2012/03/05 14:59:29
  • 終了:2012/03/07 07:24:54

回答(4件)

id:oil999 No.1

oil999回答回数1728ベストアンサー獲得回数3202012/03/05 15:15:01

ポイント50pt

ご質問にあるレコードを見ると、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

他2件のコメントを見る
id: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はユーザーが入力するので
ユーザーが入力した値をそのままカラムに格納することは、普通ありません。
回答欄に示したリンク先を参考にしてください。

2012/03/05 16:54:04
id:seadwell

何度も恐縮です。

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

2012/03/05 18:22:50
id:jranar No.2

くろふね回答回数98ベストアンサー獲得回数292012/03/05 15:32:12スマートフォンから投稿

ポイント50pt

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

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

id:seadwell

concatですか?
質問にもありますが
http://okwave.jp/qa/q2634613.html
で『素人の遊び』と書かれていれば、では効率のいい方法があるのかな・・・と思いました。
素人ですが。

商品名にユーザーがタグをつけ、どちらでも検索できるようにしたいのです。
動く方法でなく、テーブル設計も含め効率のいい方法のアドバイスを希望します。
できれば、サンプルまであると助かります。

2012/03/05 16:01:18
id:seadwell

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

2012/03/05 17:55:02
id:oil999 No.3

oil999回答回数1728ベストアンサー獲得回数3202012/03/05 18:41:51

ポイント50pt

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

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

id:seadwell

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

2012/03/06 02:28:19
id:guki No.4

もすぴー回答回数51ベストアンサー獲得回数12012/03/05 19:53:27

ポイント50pt

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

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

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

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

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

id:seadwell

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

2012/03/06 02:34:44

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません