SQL Server で主要なワイルドカード全文検索を機能させるにはどうすればよいですか?

StackOverflow https://stackoverflow.com/questions/3400

  •  08-06-2019
  •  | 
  •  

質問

注記:午前 SQL の全文検索機能、CONTAINS 句などを使用します。* は全文のワイルドカードであり、% は LIKE 句のみに使用されます。

私は今、いくつかの場所で「先頭のワイルドカード」検索を読んだことがあります(例:「stackoverflow」と一致させるために「*overflow」を使用することは、MS SQL ではサポートされていません。の使用を検討しています 正規表現一致を追加する CLR 関数, 、しかし、私は人々が他のどのような解決策を持っているのかを見ることに興味があります。

より詳しい情報: アスタリスクは単語または語句の末尾にのみ追加できます。 - 私の経験的な経験とともに:次のような単純なクエリを実行すると、「myvalue」と一致する場合、「my*」は機能しますが、「(アスタリスク)value」は一致を返しません。

SELECT * FROM TABLENAME WHERE CONTAINS(TextColumn, '"*searchterm"');

したがって、回避策が必要です。私はサイト内の検索を実際の検索ページでのみ使用しているため、基本的に Google の動作と同じように機能する必要があります (ジョー シックスパック タイプのユーザーから見て)。それほど複雑ではありませんが、この種の一致は実際には失敗すべきではありません。

正しい解決策はありません

他のヒント

先頭のワイルドカードのみの回避策:

  • 反転したテキストを別のフィールド (またはマテリアライズド ビュー) に保存します
  • この列に全文インデックスを作成します
  • * で反転されたテキストを検索します

    SELECT * 
    FROM TABLENAME 
    WHERE CONTAINS(TextColumnREV, '"mrethcraes*"');
    

もちろん、多くの欠点がありますが、簡単な回避策として...

コンテナ安定性は言うまでもありません...

先頭のワイルドカードの問題:インデックスを作成できないため、テーブル全体のスキャンを実行することになります。

単語またはフレーズの末尾にワイルドカード「*」を使用することができます (前方一致検索)。

たとえば、このクエリではすべての「datab」、「database」、「databases」...が検索されます。

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"datab*"')

ただし、残念ながら、先頭のワイルドカードを使用して検索することはできません。

たとえば、このクエリでは「データベース」は見つかりません。

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')

おそらくこのスレッドをわかりやすくするために、2008 R2 での私のテストから、上記の Franjo は正しいです。全文検索を扱う場合、少なくとも CONTAINS 句を使用する場合は、先頭に , 、末尾のみ 機能的に。* はワイルドカードであり、全文の % ではありません。

* を無視することを提案する人もいます。それはそうではないようです。私の結果は、末尾の * 機能が機能することを示しているようです。先頭の * はエンジンによって無視されると思います。

ただし、追加の問題は、ワイルドカードを含むフルテキストを使用する、末尾に * が付いている同じクエリが 2005 では比較的高速 (20 秒) で動作しましたが、データベースを 2008 R2 に移行した後は 12 分まで遅くなったことです。少なくとも他の 1 人のユーザーが同様の結果を出していたようで、彼はフォーラムの投稿を開始し、私がそれに追加しました...FREETEXT は依然として高速に動作しますが、2008 で CONTAINS の末尾 * を処理する方法で何かが変わったようです。アップグレード アドバイザーでは、全文を「改善」したためコードが壊れる可能性があるというあらゆる種類の警告が表示されますが、残念ながら、特定の非推奨のコードなどについては具体的な警告は表示されません。...変更されたという免責事項だけなので、ご自身の責任で使用してください。

http://social.msdn.microsoft.com/Forums/ar-SA/sqlsearch/thread/7e45b7e4-2061-4c89-af68-febd668f346c

おそらく、これはこれらの問題に関連する MS のヒットに最も近いものです... http://msdn.microsoft.com/en-us/library/ms143709.aspx

留意すべき点の 1 つは、主要なワイルドカード クエリは、他のワイルドカードの使用と比較して、パフォーマンスが大幅に向上するということです。

SQL Server のワイルドカード文字は、 % 署名すると、先頭、末尾、またはその他の場合でも、問題なく機能します。

そうは言っても、本格的な全文検索を行う予定がある場合は、全文インデックス機能を利用することを検討します。使用する % そして _ ワイルドカードを使用すると、データベースのパフォーマンスに深刻な影響が生じます。

SQL Server Books Online より:

Microsoft SQL Server 2005にフルテキストクエリを記述するには、Contains and Freetext Transact-SQL Prendicates、およびCantaptableおよびFreeTextable Rowset Valued関数を使用する方法を学ぶ必要があります。

つまり、上で % と _ を使用して記述されたクエリはすべて、有効な全文クエリではありません。

CONTAINSTABLE 関数を呼び出したときのクエリのサンプルを次に示します。

ランク]、[tableNameから]を選択します。

ワイルドカード検索を使用していることを CONTAINSTABLE 関数に認識させるには、ワイルドカード検索を二重引用符で囲む必要があります。先頭または末尾にワイルドカード文字 * を使用できます。CONTAINSTABLE 関数の検索文字列を作成するときに実行できることは他にもたくさんあります。別の単語の近くの単語を検索したり、語形変化のある単語 (drive = drive、drove、driving、driven) を検索したり、別の単語の同義語を検索したりできます (金属にはアルミニウムやスチールなどの同義語があります)。

テーブルを作成し、テーブルに全文インデックスを配置し、いくつかのテスト検索を実行しましたが、問題はなかったので、ワイルドカード検索は意図したとおりに機能します。

[アップデート]

質問を更新したことがわかり、いずれかの関数を使用する必要があることがわかりました。

先頭にワイルドカードを使用して検索することはできますが、ワイルドカードに続く単語が完全な単語ではない場合は、末尾に別のワイルドカードを追加する必要があります。

Example:  "*ildcar" will look for a single word as long as it ends with "ildcar".

Example:  "*ildcar*" will look for a single word with "ildcar" in the middle, which means it will match "wildcard".  [Just noticed that Markdown removed the wildcard characters from the beginning and ending of my quoted string here.]

[アップデート #2]

Dave Ward - 関数の 1 つでワイルドカードを使用しても、パフォーマンスに大きな影響を与えることはありません。「*」だけで検索文字列を作成した場合、すべての行は返されず、テスト ケースでは 0 レコードが返されました。

参考までに、Google は部分文字列の検索や右または左の切り捨てを行いません。フレーズ内の未知の単語を検索するためのワイルドカード文字 * はありますが、単語ではありません。

Google は、ほとんどの全文検索エンジンと同様に、単語のアルファベット順に基づいて、ソース文書へのリンクを含む逆索引を設定します。二分検索は、巨大なインデックスであっても非常に高速です。しかし、この場合、左切り捨てを行うのは非常に困難です。インデックスの利点が失われるからです。

ストアド プロシージャのパラメータとして、次のように使用できます。

ALTER procedure [dbo].[uspLkp_DrugProductSelectAllByName]
(
    @PROPRIETARY_NAME varchar(10)
)
as
    set nocount on
    declare @PROPRIETARY_NAME2 varchar(10) = '"' + @PROPRIETARY_NAME + '*"'

    select ldp.*, lkp.DRUG_PKG_ID
    from Lkp_DrugProduct ldp
    left outer join Lkp_DrugPackage lkp on ldp.DRUG_PROD_ID = lkp.DRUG_PROD_ID
    where contains(ldp.PROPRIETARY_NAME, @PROPRIETARY_NAME2)

全文検索に関しては、私の予算ではこれに勝るものはありません ルシーン. 。があります .Netポートが利用可能 Java バージョンで作成されたインデックスと互換性があります。

インデックスを作成/維持する必要があるため、少し作業が必要ですが、検索速度は素晴らしく、あらゆる種類の興味深いクエリを作成できます。インデックス作成速度も非常に優れており、1 日に 1 回インデックスを完全に再構築するだけで、更新について心配する必要はありません。

例として、 この検索機能 Lucene.Net を利用しています。

おそらく、次のリンクが、このワイルドカードの使用に対する最終的な答えを提供するでしょう。 FTS ワイルドカード検索の実行.

次のような一節に注目してください。「ただし、「」を指定すると、チェーン」または「Ch」「ain」では、期待した結果が得られません。アスタリスクは、ワイルドカード文字ではなく、通常の句読点とみなされます。」

全文検索エンジンの単語リストにアクセスできる場合は、このリストに対して「いいね」検索を実行し、見つかった単語とデータベースを照合することができます。次の単語を含むテーブル「words」:

    pie
    applepie
    spies
    cherrypie
    dog
    cat

このデータベース内の「pie」を含むすべての単語を、フィールド「text」を持つ fts テーブル「full_text」で照合するには、次のようにします。

    to-match <- SELECT word FROM words WHERE word LIKE '%pie%'
    matcher = ""
    a = ""
    foreach(m, to-match) {
      matcher += a
      matcher += m
      a = " OR "
    }
    SELECT text FROM full_text WHERE text MATCH matcher

%は任意の数の文字に一致します_単一の文字に一致する

フルテキスト インデックスを使用したことはありませんが、T-SQL 文字列関数のビルドを使用するだけで、かなり複雑で高速な検索クエリを実行できます。

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top