web-dev-qa-db-ja.com

WHERE句の文字列から特定の単語を除外する

請求書を保存するテーブルがあり、それから統計を取得しようとしていますが、残念ながらテーブルの作成が不十分であり、nvarcharフィールドにいくつかの重要な情報が混ざっています。料金の免除は、フロントエンドによって解析される非常にdaliesque文字列のこのフィールドに存在します。 3453.234;exempt;Invoice Total...

したがって、いくつかの単語を除外するクエリを作成します。私の問題は、キーワードのリスト(キャンセル、免除)に応じてレコードを除外できるクエリを実行する方法です。そのため、この単語のいずれかがフィールドにある場合、金額は考慮されません。

3
Nelz

それを行うクエリを作成することはそれほど難しくありません。最初に、ワイルドカードを使用したLIKEを使用してテーブルを結合するクエリを作成します。次に、このクエリからすべてを除外します。

私の意味を確認するには、次の簡単な例を参照してください。 http://sqlfiddle.com/#!6/619fb/2

あるいは、ここで例を再現しました:

--Create tables for comparing data
CREATE TABLE Invoice
(
  InvoiceID INT NOT NULL IDENTITY,
  InvoiceData varchar(200) NOT NULL,
);

CREATE TABLE BadWords
(
  BadWordID INT NOT NULL IDENTITY,
  BadWord varchar(10) NOT NULL
);

--Insert data
INSERT INTO Invoice (InvoiceData)
VALUES ('This is some invoice data'), ('it is about'), ('something interesting that'),
('you should look at'), ('because its got invoice information');

INSERT INTO BadWords (BadWord)
VALUES ('this'),('invoice');

--Test query:
SELECT *
FROM Invoice
WHERE InvoiceID NOT IN (
  SELECT InvoiceID
  FROM Invoice i
  INNER JOIN BadWords b ON i.InvoiceData LIKE '%' + b.BadWord + '%'
)

数十万行ある場合、パフォーマンスに問題がある可能性があります。詳細な情報がないと、パフォーマンスの高いクエリを提供することは困難です(たとえば、NOT CONTAINSフリーテキストクエリを使用すると、パフォーマンスが向上する可能性があります)。

7
blobbles

全文検索 は、複雑な文字列をインデックス化するためのより豊かな方法です。ケースに文章が含まれていないことは承知しておりますが、FTSは引き続き機能します。

ワイルドカード検索の代わりに、連結された値を別々の部分に分割できます。これを達成するには多くの方法があります。 this のリンクを読むと、適切なリンクが表示されます。次に、データをセットワイズに処理できます。これは、nvarchar内の位置が一貫しているか、少なくとも明確に定義されていることを前提としています。

次のいずれかの方法で、クエリを実行するたびにテーブルスキャンが発生する可能性があります。a)述語に先行ワイルドカードがある場合、パーサーはインデックスを使用しません。またはb)フィルターする前に値を分割する必要があります。 。

何らかの方法で分割された値を含むビューにインデックスを付けることができれば、適切に機能する可能性があります。

2
Michael Green
select * 
from invoice 
where invoicedata not like '%invoice%' 
or invoicedata not like '%this%'
1