php & MySQL


作成している掲示板にタグ機能をつけたいと思っています。以前はユーザーごとにタグをスペースで区切り、入力してもらいそれを毎回新しいレコードを作製し userid にユーザー名を day に日にちを topicsid に掲示板レス番号を tags にタグを半角スペース1つで区切ったものを全て格納していました。

それで、 hatena というタグを選択した際、tags にhatenaという単語が入っている全ての topicsid を表示し関連のあるスレを表示できるようにしていました。SQLは SELECT * FROM `tag` WHERE `day` = '".$today."' AND (`tags` = '".$tag."' OR `tags` LIKE '".$tag." %' OR `tags` LIKE '% ".$tag." %' OR `tags` LIKE '% ".$tag."'); です。

しかしこの方法だとDB上には格納されているにもかかわらず、1つのレコードにスペースで区切られたたくさんのタグが入っている場合や、長いタグや、韓国語や中国語などのタグがしっかりと選択されません。なにかいいタグシステムの方法はないでしょうか?

よろしくお願いします。

回答の条件
  • 1人3回まで
  • 登録:2006/07/27 12:12:06
  • 終了:2006/07/28 21:39:14

ベストアンサー

id:bonlife No.3

回答回数421ベストアンサー獲得回数752006/07/28 18:34:06

ポイント38pt

方法は2つあります。


1つ目は、whileの繰り返しの中でtag用のテーブルにアクセスし、bbsのidに紐付くtagを取得する方法です。

(前提条件として、tag用のテーブルにbbsのidが含まれている必要があります。)

bbsテーブルから取得した$row->idを検索条件としてtagテーブルにSELECTを発行し、関連するtag情報を取得します。

ただし、この方法ではDBへのアクセス(SELECTの発行)が1投稿の表示につき1回発生することになり、速度低下の可能性が高いです。


2つ目は、tag用のテーブルに加えてbbs用のテーブルにもtagの情報を持つ方法です。

投稿の登録時に以下のように2つのテーブルにtagの情報を書き込んでおきます。

  • 入力されたtag情報を分解し、特定の区切り文字(例えば半角スペース)を追加した状態でbbs用テーブルの1つの列に保存
  • 分解されたtag情報をタグ管理用のテーブルに1タグ1行で登録

この場合、一覧表示時には、bbsテーブルからtag情報を取得します。

この方法であれば、DBへのアクセス回数を抑えることができます。

ただし、tag情報が1つの列にまとめて格納されておりますので、DBからデータを取得後、分割、置換(ハイパーリンクの設定)などを行う必要はあります。

また、tagをキーにして情報を取得したい場合は、tag用のテーブルから情報を取得します。


試していないのではずしているかもしれませんが、1つ目よりも2つ目の方が少なくとも一覧表示は速いと思います。

参考になれば幸いです。

id:esecua

なるほど、早速試してみたいと思います。

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

2006/07/28 21:36:44

その他の回答(3件)

id:katsube No.1

katsube回答回数133ベストアンサー獲得回数72006/07/27 12:28:19

ポイント25pt

DBでは縦持ちに変更すると言う方法は検討済みでしょうか?

○入力

  タグ=aa bb cc

 記事ID=111111


○処理

 入力されたタグをスペースで分割し、それぞれINSERTする。

  ※テキストファイルに記録し、バッチ(cron)で

   10分に1回程度インポートという手もあります。

○DB

 タグ | 記事ID

 --------------

 aa  | 111111

 bb  | 111111

 cc  | 111111


で、以下のように検索、

select distinct 記事ID from table_name where タグ='aa'

id:esecua

katsubeさんありがとうございました。早速実装してみたいと思います。

2006/07/27 15:51:02
id:bonlife No.2

回答回数421ベストアンサー獲得回数752006/07/27 13:02:20

ポイント27pt

以前、少し似ている質問があり、回答したのですが、そちらが参考になると思います。

一度確認してみてください。

考え方はid:katsubeさんと同様です。

検索時の負荷はより小さくなります。

(検索はできるだけLIKEを使わずに完全一致で行うような仕組みを考えるとINDEXが活きてきます。)

参考になれば幸いです。

id:esecua

いつもありがとうございます。

早速実装してみたんですが、別のtag用テーブルとメインデータを格納しているbbsテーブルがあります。

各トピックすを表示する際、while()を使い

$sql = "select * from table_name...."

...

while ($row = mysql_fetch_object($res)) {

echo $row->topics_name"
";

echo $row->id;

}

のようにbbsのテーブルにあるデータは表示できるのですが、tagは別のテーブルなのでこれを同時に同じところに表示するにはどうすればいいのでしょうか?

よろしくお願いいたします。

2006/07/28 12:38:27
id:bonlife No.3

回答回数421ベストアンサー獲得回数752006/07/28 18:34:06ここでベストアンサー

ポイント38pt

方法は2つあります。


1つ目は、whileの繰り返しの中でtag用のテーブルにアクセスし、bbsのidに紐付くtagを取得する方法です。

(前提条件として、tag用のテーブルにbbsのidが含まれている必要があります。)

bbsテーブルから取得した$row->idを検索条件としてtagテーブルにSELECTを発行し、関連するtag情報を取得します。

ただし、この方法ではDBへのアクセス(SELECTの発行)が1投稿の表示につき1回発生することになり、速度低下の可能性が高いです。


2つ目は、tag用のテーブルに加えてbbs用のテーブルにもtagの情報を持つ方法です。

投稿の登録時に以下のように2つのテーブルにtagの情報を書き込んでおきます。

  • 入力されたtag情報を分解し、特定の区切り文字(例えば半角スペース)を追加した状態でbbs用テーブルの1つの列に保存
  • 分解されたtag情報をタグ管理用のテーブルに1タグ1行で登録

この場合、一覧表示時には、bbsテーブルからtag情報を取得します。

この方法であれば、DBへのアクセス回数を抑えることができます。

ただし、tag情報が1つの列にまとめて格納されておりますので、DBからデータを取得後、分割、置換(ハイパーリンクの設定)などを行う必要はあります。

また、tagをキーにして情報を取得したい場合は、tag用のテーブルから情報を取得します。


試していないのではずしているかもしれませんが、1つ目よりも2つ目の方が少なくとも一覧表示は速いと思います。

参考になれば幸いです。

id:esecua

なるほど、早速試してみたいと思います。

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

2006/07/28 21:36:44
id:shotets No.4

堺ちゃん回答回数42ベストアンサー獲得回数22006/07/27 13:27:26

区切りを半角スペース以外にしちゃダメですか?

カンマとかタブ(¥t)とか<>とか

id:esecua

え?

2006/07/28 21:38:21

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

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

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

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

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