2016-05-24 17 views
0

ユーザーがWebサイト上のテキストを検索するたびに、検索テキストがsearch_tableに記録されます。サブ検索も記録されます。それらはアスタリスクで記録されています。SQL - テーブルの列内で最も完全な文字列を検索する

目的は、ユーザーが検索した最も完全な検索テキストを見つけることです。

理想的な方法は次のようになります。

 Group the ids = 1,4,6 and obtain id=6 
     Group the ids = 2,5,7 and obtain id = 7 
     Group the ids = 3 and obtain id = 3 
     Group the ids 8, 9 and obtain id = 9 

search_tableの

  id user search_text 
      -------------------- 
      1 user1 data manag* 
      2 user1 confer* 
      3 user1 incomplete sear* 
      4 user1 data managem* 
      5 user1 conference c* 
      6 user1 data management 
      7 user1 conference call 
      8 user1 status in* 
      9 user1 status information 

出力はあなたが助けてくださいすることができ

 user search_text 
     --------------------- 
     user1 data management 
     user1 conference call 
     user1 incomplete sear* 
     user1 status information 

すべきですか?これは、他の一部であるすべての検索をフィルタリングしている

SELECT * FROM 
    SEARCH_TABLE st 
    WHERE 
    NOT EXISTS (

    SELECT 1 FROM 
     SEARCH_TABLE st2 
     -- remove asterkis and ad % 
     WHERE st2.search_Text LIKE replace(st.search_text,'*','')||'%' 
    ) 

:以下のような

+0

選択から外しIDだから問題は関係なく、あなたはそれが本当の単語であるかどうかを判断するために側に座って辞書ファイルを持っている必要がありますやっているのです。さもなければ、それはより大きいか、またはより完全であるので、「データ管理」に終わるでしょう。あなたはスクリプト言語やストアドプロシージャが必要になります – FirebladeDan

+0

@ FirebladeDanユーザーが "data managementzzz"を検索したとしても、それは問題ないと思います。それは通常のクエリで行うことができます、そうですか? – lambda9

+0

"data managementzzz"の検索は、アプリケーションで「データ管理」と同じ動作を示しますか?それがええなら、あなたはあなたが言っていることをグループ化し、最大を選ぶことができますが、これは行動であるとは思わない。起こるのは "data mana"が正しい結果を生み出すのに対し、 "data managementzzz"はおそらく0と一致します。 – FirebladeDan

答えて

0

何かが作業を行う必要があります。

+0

私はこれを試してくれます。 – lambda9

+0

それがうまくいくなら、答えを受け入れてください:) – mjpolak

0

これはおそらく、最もエレガントな方法はありませんが、ここではそれで行くのです:

alter table your_table 
    add group_id int 

    select [user], left(search_text, 5) as Group_Text, IDENTITY(int, 1,1) as Group_ID 
    into #group_id_table 
    from your_table 
    group by [user], left(search_text, 5) 
    order by [user], left(search_text, 5) 

    update a 
    set a.group_id = b.group_id 
    from your_table as a 
    join #group_id_table as b 
    on left(search_text, 5) = group_text 

    select [user], max(search_text), group_id 
    from your_table 
    group by [user], group_id 
    order by [user], group_id 

ユーザーオフgroup_idの年代を基づかしているので、これは私がそれを実行した場合に所望の結果を達成し、もちろん指定された文字列の長さに問題がある可能性があります。私はこれがあなたのために仕事をすることを願っています。

+0

ありがとう私はこれを試してみます – lambda9

0

このショットを投稿してください。私は完成したテキスト(およびその短い部分)を分けて、各レコードの最長部分を見つけました。 OracleではPostgreSQLへのアクセス権がないのでテストしましたが、エキゾチックなものを使用していないため、動作するはずです。

with 
    --Contains all completed searches 
    COMPLETE as (select * from SEARCH_TABLE where SEARCH_TEXT not like '%*'), 
    --Contains all searches that are incomplete and dont have a completed match 
    INCOMPLETE as (
    select S.* 
    from SEARCH_TABLE S 
    left join COMPLETE C 
     on S.USR = C.USR 
     and C.SEARCH_TEXT like replace(S.SEARCH_TEXT, '*', '%') 
    where C.ID is null 
), 
    --chains all incompleted with any matching pattern shorter than it. 
    CHAINED_INC as (
    select LONGER.USR, LONGER.ID, LONGER.SEARCH_TEXT, SHORTER.SEARCH_TEXT SEARCH_TEXT_SHORT 
    from INCOMPLETE LONGER 
    join INCOMPLETE SHORTER 
     on LONGER.SEARCH_TEXT like replace(SHORTER.SEARCH_TEXT, '*', '%') 
     and LONGER.ID <> SHORTER.ID 
) 
--if a text is not the shorter text for a different record, that means it's the longest text for that pattern. 
select distinct T1.USR, T1.SEARCH_TEXT 
from CHAINED_INC T1 
left join CHAINED_INC T2 
    on T1.USR = T2.USR 
    and T1.SEARCH_TEXT = T2.SEARCH_TEXT_SHORT 
where T2.SEARCH_TEXT_SHORT is null 
--finally, union back to the completed texts. 
union all 
select USR, SEARCH_TEXT from COMPLETE 
; 

編集:

関連する問題