[MySQL] タグを含むテキストを項目に格納している場合、タグを除いたテキストで検索をかけることはできますか?


別カラムにタグを除いたテキストを格納しておくしかないのでしょうか?text型だとレコード長が大きくなるのでできればそれはやりたくないです。なにかいい方法はないでしょうか?

回答の条件
  • 1人2回まで
  • 登録:2006/07/05 22:34:49
  • 終了:2006/07/12 22:35:02

回答(3件)

id:m-nisi No.1

m-nisi回答回数159ベストアンサー獲得回数32006/07/05 23:33:14

ポイント27pt

例えば、テストこんな感じで格納されてるのですか?

とすると、

where key like '<%>テスト</%>'

こんな感じでいけないでしょうか?

見当違いなら申し訳ないです。

id:k2017

ありがとうございます。

テスト

で格納されているとすると、

where key like '%strong%'

でマッチしてしまいます。

'テスト'にはマッチするけど'strong'にはマッチしないという方法を知りたいのです。

2006/07/05 23:54:01
id:m-nisi No.2

m-nisi回答回数159ベストアンサー獲得回数32006/07/06 01:24:24

ポイント27pt

今、WindowsのMySQL5で試した所、

前述した方法で出来ましたよ。

where key like '%strong%'

ではなくて

where key like '<%>strong</%>'

です。

テストに用いたデータは

> select * from test;

+----------+---------------------------+

|  id |     text      |

+----------+---------------------------+

|  1  |<strong>test</strong>|

|  2  |  <b>test2</b>  |

|  3  |  <i>test3</i>  |

|  4  |  <a>test4</a>  |

|  5  | <div>strong</div> |

+----------+--------------------------+

です。

>select * from test where text like '%strong%';

+----------+---------------------------+

|  id |     text      |

+----------+---------------------------+

|  1  |<strong>test</strong>|

|  5  | <div>strong</div> |

+----------+--------------------------+

となりますが、

> select * from test where text like '<%>strong</%>';

とすると

+----------+---------------------------+

|  id |     text      |

+----------+---------------------------+

|  5  | <div>strong</div> |

+----------+--------------------------+

こうなります。

strongがタグ名にもテキストの中にも含まれてた時に、

タグの方は引っかからないという事です。

例えば、以下のようにすると、

> select * from test where text like '<%>div</%>'

何もひっかからないです。

あと、<と>は全て半角で記述してください。

汚い表ですみません。

はてなさん、勝手にタグ解釈とかパイプ解釈とかするから

こういうの書きづらい。

id:k2017

ありがとうございます。そうですね、前述の方法でできますね。すみません。

ただ、質問では省略しましたがデータは

・タグが入っているかどうか分からない

・タグが入れ子になっている可能性もある

という感じでも上手くいくようにしたいです。

2006/07/06 01:37:41
id:kamekichi3 No.3

kamekichi3回答回数15ベストアンサー獲得回数02006/07/06 06:17:51

ポイント26pt

>・タグが入っているかどうか分からない

>・タグが入れ子になっている可能性もある

ということでは完全なる不確定要素となってしまい条件として使えない気がします。

ストアドプロシージャで対応したり、抜き出したデータをプログラム側で正規表現置換をかけ、タグの部分を削除してしまった方が簡単なのではないでしょうか?

どうしてもSQLで実現しないといけない理由があるようでしたら、横レスになってしまってすみません。

id:k2017

ありがとうございます。

もしMySQLに「あるデータ型ならselectでタグを削除してから検索してくれる」とか「selectのときにこの関数を挟めばタグを無視して検索してくれる」とかそういう機能があればいいなと思って質問してみました。

できなければそれはそれで仕方ないですね。

textカラムをほぼ同じ内容で持つのはどうもスマートではないような気がしてなりません。

2006/07/06 17:56:15
  • id:potassium634iodide828
    もうこの質問が投稿されてから10年越しになりそうな勢いですが、
    私も同じ悩みにぶち当たり、このページにたどり着きました。
    私も散々悩みましたが、質問者様の希望に答えられるだろう解決方法を発見しました。
    MySQLというか、そもそもSQL自体に、タグを除外する機能・関数は確かに無いです。
    しかし、ユーザ定義関数というのを使えば、できます。

    まず、以下のコードをコピペして、適当なテキストファイルにして保存します。
    拡張子は何でもいいけど、「.sql」が無難でしょう。


    DELIMITER //
    DROP FUNCTION IF EXISTS `STRIP_TAGS`//
    CREATE FUNCTION STRIP_TAGS( x longtext) RETURNS longtext
    LANGUAGE SQL NOT DETERMINISTIC READS SQL DATA
    BEGIN
    DECLARE sstart INT UNSIGNED;
    DECLARE ends INT UNSIGNED;

    IF x IS NOT NULL THEN
    SET sstart = LOCATE('<', x, 1);
    REPEAT
    SET ends = LOCATE('>', x, sstart);
    SET x = CONCAT(SUBSTRING( x, 1 ,sstart -1) ,SUBSTRING(x, ends +1 )) ;
    SET sstart = LOCATE('<', x, 1);
    UNTIL sstart < 1
    END REPEAT;
    END IF;

    RETURN x;
    END;
    //


    ※出典:https://gist.github.com/kijtra/3074750

    そして、お使いのMySQLのDBで、そのファイルをインポートします。
    これは、DB内で行う、関数の宣言のようなものです(ユーザ定義関数)。
    これで、あなたのDBのSQLで、「STRIP_TAGS」という関数が使えるようになります。


    そして、SQLを

    select * from test where STRIP_TAGS(key) like '%テスト%'

    とすれば、解決します。
    こういうSQLを書けば、
    SELECT文によるそもそもの検索対象からタグが除外された状態で検索してくれます。
    つまり、

    select * from test where STRIP_TAGS(key) like '%これはテストです%'

    というSQLで、

    「これは<strong>テスト</strong>です」 にも
    「<strong>これはテストです</strong>」 にも
    「これはテストです」 にも
    「これは<a href="test.html">テ<strong>ス</strong>ト</a>です」 にもマッチします。


    タグの入れ子にだって対応してるんです。

    この方法、すごいと思いませんか…?
    役に立てれば、幸いです。
  • id:potassium634iodide828
    以下、補足説明です。

    上記、「お使いのMySQLのDBで、そのファイルをインポート」というのは、
    phpMyAdminなら「インポート」というボタンがあるので、そこからできます。
    CUIのMySQLなら、 「source インポートしたいファイルの絶対パス」 というコマンドで
    インポートができます。

    また、
    上記の方法なら当然、 like '%strong%' で
    「<strong>テスト</strong>」 や
    「これは<strong>テスト</strong>です」 にマッチすることはありません。
    そして、
    「英語でstrongは強いという意味です」 や
    「英語で<b>strong</b>は強いという意味です」 には、ちゃんとマッチします。


    この方法なら、質問者さまの希望に合っていると思いますが、いかがでしょう?

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

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

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

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