ユーザーが検索している特定のアドレスを持つ顧客がいます。
123一般的な方法
データベースには、以下に一致する5つの行があります。
ResidentialAddress1
=============================
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
FTクエリを実行して、これらの行を探します。検索に条件を追加するときに、各ステップを示します。
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"123*"')
ResidentialAddress1
=========================
123 MAPLE STREET
12345 TEST
123 MINE STREET
123 GENERIC WAY
123 FAKE STREET
...
(30 row(s) affected)
さて、これまでのところ、「ジェネリック」という単語を追加しました。
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')
ResidentialAddress1
=============================
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
123 GENERIC WAY
(5 row(s) affected)
素晴らしい。そして今、私はユーザーが存在することを確認したい最後のキーワードを追加します:
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"way*"')
ResidentialAddress1
------------------------------
(0 row(s) affected)
は?行がありませんか?「way*」だけをクエリするとどうなりますか?
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"way*"')
ResidentialAddress1
------------------------------
(0 row(s) affected)
最初は、おそらくそれはのせいで*
、ルートのway
後にもっと多くの文字が必要だと思いました。しかし、それは真実ではありません。
- 「123*」を検索すると「123」と一致します
- 「generic*」を検索すると「generic」と一致します
- オンラインの本によると、アスタリスクは0文字、1文字、またはそれ以上の文字と一致します
*
s&gのためだけに削除した場合はどうなりますか?
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"way"')
Server: Msg 7619, Level 16, State 1, Line 1
A clause of the query contained only ignored words.
したがって、単独で、またはルートとして、を検索することさえ許可されていないと考える人もいるかもしれません。way
しかし、これも真実ではありません。
SELECT * FROM Patrons
WHERE CONTAINS(Patrons.*, '"way*"')
AccountNumber FirstName Lastname
------------- --------- --------
33589 JOHN WAYNE
つまり、ユーザーはすべての単語を含む行を検索しています。
123一般的な方法
私は、正しく、WHERE
条項に翻訳します:
SELECT * FROM Patrons
WHERE CONTAINS(Patrons.*, '"123*"')
AND CONTAINS(Patrons.*, '"generic*"')
AND CONTAINS(Patrons.*, '"way*"')
行を返しません。これはうまくいかない、私のせいではない、そしてSQLServerはおかしいと言ってください。
注: FTインデックスを空にして、再構築しました。
アップデートワン
SELECT Lastname, ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.*, '"gen*"')
Lastname ResidentialAddress1
------------------------- ------------------------------
SAVE 123 GENERIC WAY
Genders
SAVE 123 GENERIC WAY
Patron 123 GENERIC WAY
SAVE 123 GENERIC WAY
SAVE 234 GENERIC WAY
SAVE 123 GENERIC WAY
(7 row(s) affected)
アップデート2
次のように入力したユーザーのふりをします。
123ジェネリックwa
SELECT ResidentialAddress1 FROM Patrons
WHERE CONTAINS(Patrons.ResidentialAddress1, '"123*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"generic*"')
AND CONTAINS(Patrons.ResidentialAddress1, '"wa*"')
ResidentialAddress1
------------------------------
(0 row(s) affected)
本当の問題は、ユーザーが完全に有効なものを入力していることであり、人間が期待するものをユーザーが期待することです。
アップデート3
誰かがこれをすべて求めました、それは私のせいではありません!:
CREATE TABLE [dbo].[Patrons] (
[PatronGUID] uniqueidentifier ROWGUIDCOL NOT NULL ,
[AccountNumber] [bigint] NULL ,
[FirstName] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[MiddleInitial] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Lastname] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[EyeColor] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[HairColor] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Gender] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[Birthday] [datetime] NULL ,
[Height] [int] NULL ,
[Weight] [int] NULL ,
[FacialHair] [tinyint] NULL ,
[Nationality] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[IdentifyingMarks] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[DriversLicenseNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[DriversLicenseRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[DriversLicenseCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[DriversLicenseExpires] [datetime] NULL ,
[DriversLicenseDateVerified] [datetime] NULL ,
[PassportNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PassportRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PassportCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PassportExpires] [datetime] NULL ,
[PassportDateVerified] [datetime] NULL ,
[OtherIdentificationNumber] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[OtherIdentificationRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[OtherIdentificationCountry] [varchar] (2) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[OtherIdentificationType] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[OtherIdentificationExpires] [datetime] NULL ,
[OtherIdentificationDateVerified] [datetime] NULL ,
[ResidentialAddress1] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialAddress2] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialAddress3] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialCity] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialZipCode] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialCountry] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ResidentialPhoneNumber] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[CountryOfResidence] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessAddress1] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessAddress2] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessAddress3] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessCity] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessRegion] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessZipCode] [varchar] (15) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessCountry] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessName] [varchar] (25) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[BusinessPhone] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PositionWithFirm] [varchar] (30) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[EmployerTelephone] [varchar] (20) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[MemberCardType] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PlayerStatusCode] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[AccountType] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[AccountStatus1] [varchar] (1) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[AccountStatus2] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[IsVIPExchangeRate] [tinyint] NULL ,
[ChangedUserGUID_Depricated] [uniqueidentifier] NULL ,
[ChangedUser] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[ChangedDate] [datetime] NULL ,
[ChangedWorkstation] [varchar] (50) COLLATE SQL_Latin1_General_CP1_CI_AS NULL ,
[PendingUpdates_Depricated] [varchar] (255) COLLATE SQL_Latin1_General_CP1_CI_AS NULL
) ON [PRIMARY]
GO
ALTER TABLE [dbo].[Patrons] ADD
CONSTRAINT [DF_Patrons_PatronGUID] DEFAULT (newid()) FOR [PatronGUID],
CONSTRAINT [PK_Patrons] PRIMARY KEY NONCLUSTERED
(
[PatronGUID]
) WITH FILLFACTOR = 90 ON [PRIMARY]
GO
if (select DATABASEPROPERTY(DB_NAME(), N'IsFullTextEnabled')) <> 1
exec sp_fulltext_database N'enable'
GO
if not exists (select * from dbo.sysfulltextcatalogs where name = N'TheFullTextCatalog')
exec sp_fulltext_catalog N'TheFullTextCatalog', N'create'
GO
exec sp_fulltext_table N'[dbo].[Patrons]', N'create', N'TheFullTextCatalog', N'PK_Patrons'
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'FirstName', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'MiddleInitial', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'Lastname', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'EyeColor', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'IdentifyingMarks', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress1', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress2', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialAddress3', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialCity', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialZipCode', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialRegion', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialCountry', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'ResidentialPhoneNumber', N'add', 1033
GO
exec sp_fulltext_column N'[dbo].[Patrons]', N'CountryOfResidence', N'add', 1033
GO
exec sp_fulltext_table N'[dbo].[Patrons]', N'activate'
GO
これが私を信じなかった男のスクリーンショットです:
動作するはずなのに動作しないクエリ:
動作するが役に立たないクエリ:
証明コンテンツで機能するが有用ではないクエリ:
アップデート4
クエリは次のように記述できません
CONTAINS(Patrons.*, 'words...')
FTインデックスで論理的または物理的にカバーされていないアイテムがあるため。たとえば、ユーザーは次のクエリを実行します。
2010年6月4日ianboyd619
4つのキーワードを提示します。
- 2010年6月4日
- ian
- ボイド
- 619
これは、擬似コードが次のようになっている場合に、すべての条件が真になることを望んでいることを意味します。
WHERE 6/4/2010 is in the row
AND ian is in the row
AND boyd is in the row
AND 619 is in the row
これは、次の部分的なクエリに変換されます。
WHERE --Keyword 1: 6/4/2010
(
((ChangedDate >= '20100604') AND (ChangedDate < '20100605'))
OR
((LastTransactionDate >= '20100604') AND (LastTransactionDate < '20100605'))
OR
(CONTAINS(Patrons.*, '"6/4/2010*"')
)
AND --Keyword 2: ian
(
CONTAINS(Patrons.*, '"ian*"')
)
AND --Keyword 3: boyd
(
CONTAINS(Patrons.*, '"boyd*"')
)
AND --Keyword 4: 619
(
(AccountNumber IN (SELECT CAST(619 AS bigint)))
OR
(CONTAINS(Patrons.*, '"619*"'))
)
回答者の1人は、元の質問で提示された簡略化された例を見ていました。現実の世界ではありません。複数の節があるのは間違っていると言うのは簡単です。AND