添付画像にデータベースの構成の画像を入れておきました。キーワードテーブルとデータテーブルという感じです。
私の方法では一度に500件のキーワードを回したら数分経っても結果が返ってきませんでしたので、なんとか上手く1万件程度の結果を短時間で得る方法は無いでしょうか。もちろん私でも同時進行で勉強をしながら答えを探しますが、簡単であればそのものズバリの答えを教えて頂けると大変助かります。
存在しないものを検索させるということは、結果的に全てのレコードを対象にするのと大差ないことなので、いっそのこと総当りにしてしまうほうがシンプルイズベストということになる場合も多く、とりあえずとなりますが下記のような方法をまずは提案します
(実際のデータの中身がわかれば、もっともっと高速化できる可能性はありますが、とりあえず処理ができないことには前に進めないと思いますので、とりあえずです。動作は確認してありますが1万件などではやってません)
SELECT T.name FROM ( SELECT TD.name, SUM(CASE WHEN TD.name LIKE concat('%', TK.keyword, '%') THEN 1 ELSE 0 END) AS cnt FROM calorie_datas TD, calorie_search TK WHERE (TK.created BETWEEN '2011-02-05' AND '2011-02-06') GROUP BY TD.name ) T WHERE T.cnt = 0 ;
流れとしては下記のようになっています
(1)calorie_datasの全レコード と calorie_searchの'2011-02-05'から'2011-02-06'までを総当りでぶつけ
(2)キーワードが何件含まれているかを数え
(3)数えた結果がゼロ件のものだけを最終的に出力する
存在しないものを検索させるということは、結果的に全てのレコードを対象にするのと大差ないことなので、いっそのこと総当りにしてしまうほうがシンプルイズベストということになる場合も多く、とりあえずとなりますが下記のような方法をまずは提案します
(実際のデータの中身がわかれば、もっともっと高速化できる可能性はありますが、とりあえず処理ができないことには前に進めないと思いますので、とりあえずです。動作は確認してありますが1万件などではやってません)
SELECT T.name FROM ( SELECT TD.name, SUM(CASE WHEN TD.name LIKE concat('%', TK.keyword, '%') THEN 1 ELSE 0 END) AS cnt FROM calorie_datas TD, calorie_search TK WHERE (TK.created BETWEEN '2011-02-05' AND '2011-02-06') GROUP BY TD.name ) T WHERE T.cnt = 0 ;
流れとしては下記のようになっています
(1)calorie_datasの全レコード と calorie_searchの'2011-02-05'から'2011-02-06'までを総当りでぶつけ
(2)キーワードが何件含まれているかを数え
(3)数えた結果がゼロ件のものだけを最終的に出力する
回答を頂きありがとうございます。ただ、私の環境で動かすことができないので、まずは SQL を解体してひとつずつ理解して再構築して使う必要があります。それまで少し時間がかかります。
>SELECT name FROM calorie_datas WHERE name NOT LIKE BINARY '%' . (SELECT keyword FROM calorie_search WHERE created > 2011-02-05 AND created < 2011-02-06 ORDER BY keyword DESC) . '%'
このように書くのなら、キーワード分素直にループしたほうが早いと思います。
中間一致のLIKE検索はインデックスも効きませんので、calorie_datasを全件ループしたほうが
良いと思います。calorie_search を取り出したキーワードはPHPの変数か配列に抱え込んでおく。
で、calorie_datasのnameとkeyword をPHPでパターンマッチをかけるです。
これでもそれなりの時間はかかると思います。
もし使われているDBで、全文検索機能がサポートされてるのならそれを使うのも1つの方法です。
1.calorie_datas 1レコード読む
2.keyword をPHPでパターンマッチ(keyword 分だけループ)
です。
もしくは、calorie_datasに登録する時点で、nameを単語に分解しておいて、別フィールドに登録
そのフィールドに普通に検索をかけるのなら、インデックスが効きますので
SQLでも十分許容範囲の応答速度になるはずです。
keyword 分だけループすると1日分だけで10秒かかりますね。月毎に出したいので5分から15分ってところでしょうか。難しいですね。
回答を頂きありがとうございます。ただ、私の環境で動かすことができないので、まずは SQL を解体してひとつずつ理解して再構築して使う必要があります。それまで少し時間がかかります。