2012-08-08 11 views
6

私は、データを検索してすべての引用符を無視できるようにする必要のあるサイトを持っています。SQL Server - 検索時に引用符を無視する簡単な方法はありますか?

  1. の検索ではありませんを行い、ないいけないし、で始まる単語持つ行の結果を取得:んではないを、またはいけないしていません
  2. を検索する「ハロー」「ハロー」またはこんにちはとその行の結果を取得「こんにちは」「ハロー」またはこんにちは

注:で始まる単語を持っている私はすでに、検索語に渡さ

は、私が欲しいのために引用符を除去しています

select Name 
    from tbl_MyTable 
where (Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like 'dont%' 
    or Replace(Replace(Replace(Replace(Replace(Replace(Name,'“',''),'‘',''),'''',''),'"',''),'’',''),'”','') like '% dont%'); 

現在、私のベストプラクティスは新しい列を作成することです

select Name 
    from tbl_MyTable 
where FixedName like '% dont%'; 

しかし、私は本当にこれが新しい列を作成することなく達成することができるかどうかを知りたいと、それは効率的でなければなりません:私はちょうど行うことができるように、それは(スペースで先頭に付加)引用取り除いたバージョンが含まれています。効率性、先頭とあなたのlike文で%末尾限り

select Name 
from tbl_MyTable 
where dbo.udf_StripQuotes(name) like '% dont%'; 

:その後のように見えます

CREATE FUNCTION [dbo].[udf_StripQuotes] 
(
    @String VARCHAR(MAX) 
) 
RETURNS VARCHAR(MAX) 
AS 
BEGIN 
    RETURN Replace(
     Replace(
      Replace(
       Replace(
        Replace(
         Replace(@String,'“',''), 
        '‘',''), 
       '''',''), 
      '"',''), 
     '’',''), 
    '”','') 
END 
GO 

:私はこのロジックを統合するユーザー定義関数を作成することをお勧め

+0

私はC#アプリケーションからクエリを実行しています。そのため、パフォーマンスを犠牲にするのではなく、その側で行うことができる小さな作業があります。私のコードは実際には複数のテーブルとカラムをクエリしています(ここでは単純化しています)、データスコープの回答が望ましいと思います。 –

答えて

1

LIKEの代わりに全文索引を使用します。

http://msdn.microsoft.com/en-us/library/ms187317.aspx

CREATE UNIQUE INDEX ix1 ON tbl_MyTable(YourKey); //unique index required 
CREATE FULLTEXT CATALOG ft AS DEFAULT; // ft is your freetext catalog name 
CREATE FULLTEXT INDEX ON tbl_MyTable(Name) 
    KEY INDEX ix1 
    WITH STOPLIST = SYSTEM; // this is your index and allows you to run the command below 

は、その後、あなたのクエリを実行するためにこれを使用:この種のもののための最速の技術だ

SELECT Name 
FROM tbl_MyTable 
WHERE FREETEXT(Name, 'dont'); 

は、あなたのフルテキストインデックスを作成します。サードパーティのフリーテキストエンジンを使用するとさらに高速化できますが、おそらくその必要はありません。

+0

解決策は次のようになります。 1)引用符を削除するFixedName列を作成します。 2)FixedName列に全文索引を作成します。 3)... 4)利益はありますか? –

+0

引用符を削除する必要はありません。名前列にフルテキストインデックスを作成するだけです。私はこれを反映するために私の答えを更新しました。 –

0

完全なテーブルスキャンを引き起こすインデックスを使用するのを防ぎます...これは、おそらくこのクエリのパフォーマンスが最大のものです。

しかし、Aaronのように、この実装はUDFを呼び出すオーバーヘッドのためオリジナルよりも遅くなります。

先行するワイルドカードを避けることができる場合は、computed column with an indexがパフォーマンスを向上させる可能性があります。

他のオプションは、Full-Text Searchを実装することだけです。

+0

これをカプセル化してクエリ内の関数を参照することは間違いありませんが、明らかであるように、これはオリジナルと同じように遅く、おそらく遅くなるでしょう。 –

+0

@AaronBertrand Hmm ...私は、最大のパフォーマンスヒットがフルテーブルスキャンから来ると思っていました...あなたは 'replace'ステートメントをudfにラップすると目立つオーバーヘッドが追加されると思いますか? –

+0

機能を呼び出す際にオーバーヘッドがあり、スキャン中に(または条件があるため)2 x行カウント関数を呼び出すことになります。私はそれを取り除くつもりで答えようとしています。 –

0

これは質問に対する回答ではありませんが、コメントとして実装することは本当に難しいでしょう。

UDFを使用してクエリ自体を簡素化する場合は、関数呼び出しを2倍ではなく、行数に制限してください。代わりに:限り根本的な問題として、私は、インデックス付き計算列がベストかもしれないとマイケルに同意するが、名前ならば、これはできません

where ' ' + dbo.udf_StripQuotes(name) like '% dont%'; 

where dbo.udf_StripQuotes(name) like 'dont%' 
    or dbo.udf_StripQuotes(name) like '% dont%'); 

これを行ってくださいカラムが900バイトを超えています(ワイルドカードのために魔法のようにスキャンをシークに陥らせることはありません)。

+0

その列の全文検索は解決策になりますか? –

0

時間的に効率的ですか?

最初のソリューションはスペース効率が良いですが、クエリが実行されるたびにテーブルの各行に複数の文字列関数を適用するため、時間効率が悪い可能性があります。

生成された列の解は空間非効率ですが、列演算を一度適用すると(列を追加してから挿入/更新するとき)時間効率が高くなる可能性があります。

ユーザーの観点からは、生成された列に対して実行される検索が最適なソリューションです。

0

引用符や二重引用符を付けずにすべての名前を返すようにしてください。これにより、LIKE文が不要になり、別の列が不要になり、クエリが高速化されます。

SELECT Replace(
    Replace(
     Replace(
      Replace(
       Replace(
        Replace(Name, '“', ''), 
       '‘', ''), 
      '''',''), 
     '"', ''), 
    '’',''), 
'”', '') AS Name 
FROM tbl_MyTable 
関連する問題