2010-10-29 41 views
2

我有一對夫婦的形式已經提供的表的凡有關

MainRecord

Record ID Details Textual Information 
    1  AAAAAAA ... some text referring to Oxford St Giles... 
    2  BBBBBBB ... some text referring Oxford.... 
    3  CCCCCCC ... some text referring to Oxford St Aldate... 

和支撐臺

地名

Record ID PlaceName 
    1  Oxford 
    1  St 
    1  Giles 
    2  Oxford 
    3  Oxford 
    3  St 
    3  Aldate 

我はnt能夠建立一個搜索詞,這樣如果我可以輸入地名的全部或部分條款。例如。如果我輸入'牛津',我會得到所有3條記錄,如果我輸入'Oxford'和'Giles',我只會得到第一條記錄 - 就像使用WHERE IN('Oxford','Giles')但條款是AND ORed?

我不知道我能否做到這一點?我曾嘗試過各種子查詢沒有成功

我使用SQL Server 2008

我想避免一個全文檢索領域

任何指針以清除霧氣將是非常有益的。

*主要記錄詳細信息更新,以避免混淆*
2個表之間的唯一聯繫是記錄ID

** **更新11月3用示例表

CREATE TABLE MAIN_RECORD (RecordID int,DocumentRef varchar(100)); 
INSERT INTO MAIN_RECORD VALUES (86, 'Doc Referring to William Samuel ADAMS'); 
INSERT INTO MAIN_RECORD VALUES (87, 'Doc Referring to William JONES'); 
INSERT INTO MAIN_RECORD VALUES (88, 'Doc Referring to Samuel SMITH'); 



CREATE TABLE FORENAMES (RecordID int,Forename varchar(25)); 
INSERT INTO FORENAMES VALUES (86, 'William'); 
INSERT INTO FORENAMES VALUES (86, 'Samuel'); 
INSERT INTO FORENAMES VALUES (87, 'William'); 
INSERT INTO FORENAMES VALUES (88, 'Samuel'); 

我初始查詢是

SELECT main.[RecordID],main.documentRef 
    FROM [MAIN_RECORD] main 
    INNER JOIN [FORENAMES] fn 
    ON main.RecordID = fn.RecordID 
    WHERE fn.ForeName IN ('William') 

這很好,並且返回

RecordID documentRef 
86 Doc Referring to William Samuel ADAMS 
87 Doc Referring to William JONES 

同上塞繆爾等

我的問題是,當我在錄名字搜索領域超過1項即

SELECT main.[RecordID],main.documentRef 
    FROM [MAIN_RECORD] main 
    INNER JOIN [FORENAMES] fn 
    ON main.RecordID = fn.RecordID 
    WHERE fn.ForeName IN ('William,Samuel') 

這將返回什麼。

我需要這個只返回主記錄,它有塞繆爾和威廉在它,即。當搜索詞有多個名稱時。
它還需要找到威廉塞繆爾以及塞繆爾威廉。

從別人的帖子,我已經下降司的途徑,並提出如下(將主要選擇之前的一些字符串操作):

DECLARE @Forename nvarchar(max) 
DECLARE @SQLCommand nvarchar(max) 
DECLARE @Number_of_Terms int 
SET @Forename = 'William,Samuel' 
--SET @Forename = 'Samuel,William' 
--SET @Forename = 'William' 
--SET @Forename = 'Samuel' 
SET @Number_of_Terms = LEN(@Forename) - LEN(REPLACE(@Forename,',',''))+1 
SET @Forename = REPLACE(@Forename,',',''',''') 

SET @SQLCommand = 'SELECT fr.RecordID FROM dbo.BRS109_FullRecord fr '+ 
'INNER JOIN dbo.BRS109_Forenames fn '+ 
'ON fr.RecordID = fn.RecordID '+ 
'WHERE fr.RecordID = fn.RecordID '+ 
'AND fn.forename IN ('''[email protected] +''') ' + 
' GROUP BY fr.RecordID ' + 
' HAVING COUNT(fr.RecordId) = ' + CAST(@Number_of_Terms AS varchar(2)) + 
' ORDER BY fr.RecordId' 

EXECUTE sp_executesql @SQLCommand 

這似乎給我我所期待的。

非常感謝所有爲特別貢獻「Quassnoi」和「onedaywhen」 - 非常有幫助

+2

只是出於好奇:你爲什麼要避免全文搜索? – 2010-10-29 12:14:57

+0

當然不是用一切手段 - 它的東西,我們將着眼於後INTIAL緊迫性已經結束。 – 2010-10-29 12:23:07

+0

注意,有問題的地方實際上是所謂阿爾達特街(http://en.wikipedia.org/wiki/St_Aldate's,_Oxford);) – onedaywhen 2010-10-29 13:51:34

回答

0

使用LIKE語句 像這樣:

SELECT * 
FROM table AS t 
WHERE t.PlaceName LIKE "%Oxford%" AND t.PlaceName LIKE "%Giles%" 

使用這個查詢,你將不再需要第二個表, 一切都將通過第一個

+1

然而,對於'Ford'搜索將返回'Milford','Stanford' ... – 2010-10-29 12:17:53

1

不能完全確定在您的環境中完成,但在Oracle中,這一項應該工作。

select * from mainrecord 
where placename like '%Oxford%' 
INTERSECT 
select * from mainrecord 
where placename like '%Giles%' 
0

如果這是你所需要的,你可以像使用

SELECT PlaceName FROM PlaceNames WHERE PlaceName LIKE "%Oxford%" AND PlaceName LIKE "%Giles%" 

如果您需要多一點靈活性(如限制匹配到整個單詞),你可以add Regex search to SQL Server輕鬆

SELECT PlaceName FROM PlaceNames WHERE dbo.RegExMatch(PlaceName,'\bOxford\b') = 1 
AND dbo.RegExMatch(PlaceName,'\bGiles\b') = 1 
5
SELECT * 
FROM mainrecord mr 
WHERE (
     SELECT COUNT(*) 
     FROM placenames pn 
     WHERE pn.record = mr.record 
       AND pn.placename IN ('Oxford', 'St', 'Giles') 
     ) = 3 
+0

我印象深刻,這種橫向思維過程 - 在第一次測試中,它似乎正在做我以後的事情。謝謝:-) – 2010-10-29 12:44:15

2

你是否暗指relational division?例如供應所有產品的供應商,可以將所有飛機掛在衣架上的飛行員等?

如果是這樣,this article在SQL中有很多示例實現。

下面是一個使用你的數據:

WITH MainRecord (Record_ID, Details, Textual_Information) 
    AS 
    (
     SELECT Record_ID, Details, Textual_Information 
     FROM (
       VALUES (1, 'AAAAAAA', ' ... some text referring to Oxford St Giles... '), 
        (2, 'BBBBBBB', ' ... some text referring Oxford.... '), 
        (3, 'CCCCCCC', ' ... some text referring to Oxford St Aldate... ') 
      ) AS MainRecord (Record_ID, Details, Textual_Information) 
    ), 
    PlaceNames (Record_ID, PlaceName) 
    AS 
    (
     SELECT Record_ID, PlaceName 
     FROM (
       VALUES (1, 'Oxford'), 
        (1, 'St'), 
        (1, 'Giles'), 
        (2, 'Oxford'), 
        (3, 'Oxford'), 
        (3, 'St'), 
        (3, 'Aldate') 
      ) AS PlaceNames (Record_ID, PlaceName) 
    ), 
    FullSet (Record_ID, PlaceName, Textual_Information) 
    AS 
    (
     SELECT DISTINCT P1.Record_ID, P1.PlaceName, 
      M1.Textual_Information 
     FROM MainRecord AS M1 
      CROSS JOIN PlaceNames AS P1 
    ), 
    NoMatch (Record_ID, PlaceName, Textual_Information) 
    AS 
    (
     SELECT F1.Record_ID, F1.PlaceName, F1.Textual_Information 
     FROM FullSet AS F1 
       EXCEPT 
     SELECT P1.Record_ID, P1.PlaceName, 
      M1.Textual_Information 
     FROM MainRecord AS M1 
      INNER JOIN PlaceNames AS P1 
       ON M1.Textual_Information LIKE '%' + P1.PlaceName + '%' 
    ) 
SELECT F1.Record_ID, F1.PlaceName, F1.Textual_Information 
    FROM FullSet AS F1 
WHERE NOT EXISTS (
        SELECT * 
         FROM NoMatch AS N1 
        WHERE N1.Record_ID = F1.Record_ID 
          AND N1.Textual_Information = F1.Textual_Information 
        ); 

UPDATE:

我更喜歡自己的原始數據;)不管了,我建議的方法是一樣的,即關係部門(這次是更好加入):

WITH FullSet (RecordID, Forename, DocumentRef) 
    AS 
    (
     SELECT DISTINCT P1.RecordID, P1.Forename, 
      M1.DocumentRef 
     FROM MAIN_RECORD AS M1 
      INNER JOIN FORENAMES AS P1 
       ON M1.RecordID = P1.RecordID 
    ), 
    NoMatch (RecordID, Forename, DocumentRef) 
    AS 
    (
     SELECT F1.RecordID, F1.Forename, F1.DocumentRef 
     FROM FullSet AS F1 
       EXCEPT 
     SELECT P1.RecordID, P1.Forename, 
      M1.DocumentRef 
     FROM MAIN_RECORD AS M1 
      INNER JOIN FORENAMES AS P1 
       ON M1.RecordID = P1.RecordID 
        AND M1.DocumentRef LIKE '%' + P1.Forename + '%' 
    ) 
SELECT F1.RecordID, F1.Forename, F1.DocumentRef 
    FROM FullSet AS F1 
WHERE NOT EXISTS (
        SELECT * 
         FROM NoMatch AS N1 
        WHERE N1.RecordID = F1.RecordID 
          AND N1.DocumentRef = F1.DocumentRef 
        ); 
+0

哎唷!這是一些查詢,特別是當我的MainRecord可能需要超過50,000條目時。 我將編輯我原來的問題有進一步的例子和示例表。 – 2010-11-03 17:44:44

+0

我仍然認爲你並不瞭解我的問題。在更新後的版本,你有一個條款「和M1.DocumentRef LIKE‘%’+ P1.Forename +‘%’的唯一字段我想從MainRecord表中包括的是的recordId。 所以,我選擇真正需要說」給我已經聯繫其包含用的名字「威廉」和的forName「塞繆爾」 這是否有道理用的名字記錄MainRecords的RecordIDs?這個邏輯也需要擴展到姓氏字段,但我可以簡單地複製。 – 2010-11-04 10:44:48