-1

如果我在表格上有兩個全文索引,例如ContactsCompanies,我該如何編寫一個查詢來確保搜索短語的所有單詞都存在於這兩個索引的之內?如何搜索多個全文索引的ANY列中的所有單詞?

例如,如果我正在搜索聯繫人全部關鍵字存在於聯繫人記錄或公司中,我該如何編寫查詢?

我試着在接觸和公司的表都做CONTAINSTABLE,然後加入表一起,但如果我通過搜索短語中的每一個作爲'"searchTerm1*' AND '"searchTerm2*"'那麼只有當所有搜索詞都在匹配索引和返回的記錄太少。如果我通過它像'"searchTerm1*' OR '"searchTerm2*"'那麼它匹配(而不是所有任何的搜索詞在哪裏的指標要麼返回太多記錄。

我也嘗試創建一個索引視圖,將聯繫人連接到公司,這樣我就可以在一個鏡頭中搜索所有列,但不幸的是,聯繫人可能屬於多個公司,因此我將使用的ContactKey該視圖的關鍵不再是唯一的,因此無法創建。

看起來好像我可能需要分開單詞並單獨查詢每個單詞,然後將結果加回到一起以確保所有單詞都匹配,但我無法想象我如何「 d寫入該查詢。

這裏的模型可以是什麼樣子的例子:

Contact   CompanyContact Company 
-------------- -------------- ------------ 
ContactKey  ContactKey  CompanyKey 
FirstName   CompanyKey  CompanyName 
LastName 

我有名字,姓氏全文索引和其他的公司名稱。

+0

你能分享有關模型的一些信息?到目前爲止,我的理解是,您有兩個表格:聯繫人和公司,並且每個表都包含ContactKey。我猜測,ContactKey不是您正在搜索的值。 – Paurian

+0

@Paurian,請參閱我的更新,並告訴我您是否需要更多信息。謝謝。 – adam0101

+0

@BogdanSahlean引發錯誤,指出CompanyContact不能成爲CONTAINSTABLE查詢的一部分,因爲它不是全文索引的,而且我也無法向它添加全文索引,因爲該表中沒有文本。 – adam0101

回答

0

我創建了一個與任意數量的全文索引和工作的方法列。使用這種方法,可以很容易地添加額外的方面進行搜索。

  1. 斯普利特搜索短語到行的臨時表
  2. 加入到該臨時表來搜索上的每個應用的全文索引使用CONTAINSTABLE每個搜索詞。
  3. 將結果聯合在一起,並獲得找到的搜索項的不同數量。
  4. 過濾掉指定的搜索詞數與所找到的搜索詞數不匹配的結果。

例子:

DECLARE @SearchPhrase nvarchar(255) = 'John Doe' 
DECLARE @Matches Table(
    MentionedKey int, 
    CoreType char(1), 
    Label nvarchar(1000), 
    Ranking int 
) 

-- Split the search phrase into separate words. 
DECLARE @SearchTerms TABLE (Term NVARCHAR(100), Position INT) 
INSERT INTO @SearchTerms (Term, Position) 
SELECT dbo.ScrubSearchTerm(Term)-- Removes invalid characters and convert the words into search tokens for Full Text searching such as '"word*"'. 
FROM dbo.SplitSearchTerms(@SearchPhrase) 

-- Count the search words. 
DECLARE @numSearchTerms int = (SELECT COUNT(*) FROM @SearchTerms) 

-- Find the matching contacts. 
;WITH MatchingContacts AS 
(
    SELECT 
     [ContactKey] = sc.[KEY], 
     [Ranking] = sc.[RANK], 
     [Term] = st.Term 
    FROM @SearchTerms st 
    CROSS APPLY dbo.SearchContacts(st.Term) sc -- I wrap my CONTAINSTABLE query in a Sql Function for convenience 
) 
-- Find the matching companies 
,MatchingContactCompanies AS 
(
    SELECT 
     c.ContactKey, 
     Ranking = sc.[RANK], 
     st.Term 
    FROM @SearchTerms st 
    CROSS APPLY dbo.SearchCompanies(st.Term) sc 
    JOIN dbo.CompanyContact cc ON sc.CompanyKey = cc.CompanyKey 
    JOIN dbo.Contact c ON c.ContactKey = cc.ContactKey 
) 
-- Find the matches where ALL search words were found. 
,ContactsWithAllTerms AS 
(
    SELECT 
     c.ContactKey, 
     Ranking = SUM(x.Ranking) 
    FROM (
     SELECT ContactKey, Ranking, Term FROM MatchingContacts UNION ALL 
     SELECT ContactKey, Ranking, Term FROM MatchingContactCompanies 
    ) x 
    GROUP BY c.ContactKey 
    HAVING COUNT(DISTINCT x.Term) = @numSearchTerms 
) 
SELECT 
    * 
FROM ContactsWithAllTerms c 
0

此答案已重建,以解決您的問題,使得多個字符串必須跨字段存在。請注意,在CompanyContactLink鏈接表中的單個鍵:

CREATE FULLTEXT CATALOG CompanyContact WITH ACCENT_SENSITIVITY = OFF 
GO 

CREATE TABLE Contact (ContactKey INT IDENTITY, FirstName VARCHAR(20) NOT NULL, LastName VARCHAR(20) NOT NULL) 
ALTER TABLE Contact ADD CONSTRAINT PK_Contact PRIMARY KEY NONCLUSTERED (ContactKey) 

CREATE TABLE Company (CompanyKey INT IDENTITY, CompanyName VARCHAR(50) NOT NULL) 
ALTER TABLE Company ADD CONSTRAINT PK_Company PRIMARY KEY NONCLUSTERED (CompanyKey) 
GO 

CREATE TABLE CompanyContactLink (CompanyContactKey INT IDENTITY NOT NULL, CompanyKey INT NOT NULL, ContactKey INT NOT NULL) 
GO 

INSERT INTO Contact (FirstName, LastName) VALUES ('Dipper', 'Pines') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Mabel', 'Pines') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Stanley', 'Pines') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Soos', 'Ramirez') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Wendy', 'Corduroy') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Sheriff', 'Blubs') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Bill', 'Cipher') 
INSERT INTO Contact (FirstName, LastName) VALUES ('Pine Dip', 'Nobody') 
INSERT INTO Contact (FirstNAme, LastName) VALUES ('Nobody', 'Pine Dip') 

INSERT INTO Company (CompanyName) VALUES ('Mystery Shack') 
INSERT INTO Company (CompanyName) VALUES ('Greesy Diner') 
INSERT INTO Company (CompanyName) VALUES ('Watertower') 
INSERT INTO Company (CompanyName) VALUES ('Manotaur Cave') 
INSERT INTO Company (CompanyName) VALUES ('Big Dipper Watering Hole') 
INSERT INTO Company (CompanyName) VALUES ('Lost Pines Dipping Pool') 
GO 

INSERT INTO CompanyContactLink Values (3, 5), (1, 1), (1, 2), (1, 3), (1, 4), (1,5), (5,1), (3,1), (4,1) 
GO 

CREATE FULLTEXT INDEX ON Contact (LastName, FirstName) 
KEY INDEX PK_Contact 
ON CompanyContact 
WITH STOPLIST = SYSTEM 

CREATE FULLTEXT INDEX ON Company (CompanyName) 
KEY INDEX PK_Company 
ON CompanyContact 
WITH STOPLIST = SYSTEM 
GO 

CREATE VIEW CompanyContactView 
WITH SCHEMABINDING 
AS 
    SELECT 
    CompanyContactKey, 
    CompanyName, 
    FirstName, 
    LastName 
    FROM 
    dbo.CompanyContactLink 
    INNER JOIN dbo.Company ON Company.CompanyKey = CompanyContactLink.CompanyKey 
    INNER JOIN dbo.Contact ON Contact.ContactKey = CompanyContactLink.ContactKey 
GO 

CREATE UNIQUE CLUSTERED INDEX idx_CompanyContactView ON CompanyContactView (CompanyContactKey); 
GO 

CREATE FULLTEXT INDEX ON CompanyContactView (CompanyName, LastName, FirstName) 
KEY INDEX idx_CompanyContactView 
ON CompanyContact 
WITH STOPLIST = SYSTEM 
GO 

-- Wait a few moments for the FULLTEXT INDEXing to take place. 
-- Check to see how the index is doing ... repeat the following line until you get a zero back. 

DECLARE @ReadyStatus INT 
SET @ReadyStatus = 1 
WHILE (@ReadyStatus != 0) 
BEGIN 
    SELECT @ReadyStatus = FULLTEXTCATALOGPROPERTY('CompanyContact', 'PopulateStatus') 
END 

SELECT 
    CompanyContactView.* 
FROM 
    CompanyContactView 
WHERE 
    FREETEXT((FirstName,LastName,CompanyName), 'Dipper') AND 
    FREETEXT((FirstName,LastName,CompanyName), 'Shack') 
GO 

併爲你的榜樣,爲了與溫迪在沃特陶:

SELECT 
    CompanyContactView.* 
FROM 
    CompanyContactView 
WHERE 
    FREETEXT((FirstName,LastName,CompanyName), 'Wendy') AND 
    FREETEXT((FirstName,LastName,CompanyName), 'Watertower') 
GO 
+0

這隻會搜索聯繫人或公司。使用你的數據,如果我正在尋找聯繫人,Wendy是Watertower的聯繫人,如果我搜索「Wendy Watertower」,我希望找回Wendy的聯繫人密鑰,但是你沒有在聯繫人和公司之間定義任何關係。 – adam0101

+0

答案已被重建以解決您的問題;具體而言,如何在多個字段中包含多個必需的搜索字符串。 – Paurian

+0

並對其到期的地點給予一定的評價。恰巧,在徹底改變了答案之後,我開始意識到這些變化完全符合波格丹薩萊恩的建議。如果你發現這個完整的代碼解決方案是對你的問題有用的東西,請確保他的評論也是upvote。 – Paurian