2010-10-29 40 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