49

注: SQL の全文検索機能、CONTAINS 句などすべてを使用しています。* は全文のワイルドカード、% は LIKE 句専用です

「先頭のワイルドカード」検索 (「*overflow」を使用して「stackoverflow」に一致させるなど) が MS SQL でサポートされていないことをいくつかの場所で読みました。CLR 関数を使用して regex matching を追加することを検討していますが、他のソリューションがどのようなものか知りたいです。

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

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

したがって、回避策が必要です。私は実際の検索ページで自分のサイトの検索を使用しているだけなので、基本的には Google と同じように機能する必要があります (Joe Sixpack タイプのユーザーの目には)。それほど複雑ではありませんが、この種の一致は失敗するべきではありません。

4

13 に答える 13

28

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

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

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

もちろん、簡単な回避策のためだけに、多くの欠点があります...

CONTAINSTABLEは言うまでもありません...

于 2008-09-23T23:11:43.040 に答える
16

主要なワイルドカードの問題: インデックスを作成できないため、テーブル全体のスキャンを実行しています。

于 2008-08-06T14:07:59.973 に答える
10

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

たとえば、このクエリはすべての「datab」、「database」、「databases」を検索します...

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

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

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

SELECT * FROM SomeTable WHERE CONTAINS(ColumnName, '"*abase"')
于 2008-11-26T09:22:02.710 に答える
4

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

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

ただし、私の追加の問題は、ワイルドカードを含む全文を使用する末尾に * がある同じクエリが、2005 年には比較的高速 (20 秒) に機能し、db を 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

于 2011-10-06T18:17:56.623 に答える
3

CONTAINS: これは、リビジョン #2 でキーワードが導入される前に、元のバージョン #1 の質問に対して提出した回答です。それはまだ事実として正確です。

SQL Server のワイルドカード文字は%記号であり、先頭、末尾、またはそれ以外でも問題なく機能します。

とはいえ、本格的な全文検索を行う場合は、全文索引機能を利用することを検討します。%およびワイルドカードを使用_すると、データベースのパフォーマンスが大幅に低下します。

于 2008-08-06T13:57:28.683 に答える
3

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

于 2008-08-06T14:03:59.123 に答える
1

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

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

于 2008-09-16T00:22:38.610 に答える
1

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

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)
于 2016-01-04T23:59:40.290 に答える
0

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

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

例として、この検索機能は Lucene.Net によって強化されています。

于 2008-08-08T15:34:28.997 に答える
0

おそらく、このワイルドカードの使用に対する最終的な答えは、次のリンクから得られるでしょう: Performing FTS Wildcard Searches .

次の文章に注意してください。

于 2016-10-18T17:34:27.467 に答える
-1

% 任意の数の文字に一致 _ 単一の文字に一致

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

于 2008-08-06T14:00:57.600 に答える
-1

SQL Server Books Online から:

Microsoft SQL Server 2005 でフルテキスト クエリを作成するには、CONTAINS および FREETEXT Transact-SQL 述語と、CONTAINSTABLE および FREETEXTTABLE 行セット値関数の使用方法を習得する必要があります。

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

CONTAINSTABLE 関数を呼び出すときのクエリの例を次に示します。

SELECT RANK , * FROM TableName , CONTAINSTABLE (TableName, *, ' "*WildCard" ') searchTable WHERE [キー] = TableName.pk ORDER BY searchTable.RANK DESC

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

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

[アップデート]

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

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

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 レコードが返されました。

于 2008-08-06T15:08:11.130 に答える