Где в вопросе - PullRequest
       28

Где в вопросе

2 голосов
/ 29 октября 2010

У меня есть пара таблиц в форме

.

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...  

и опорный стол

PlaceNames

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

Я хочу иметь возможность составить поисковый запрос, чтобы я мог вводить все или частичные термины в географических названиях. Например. если я введу «Оксфорд», я получу все 3 записи, если я введу «Оксфорд» и «Джайлз», я получу только запись 1 - почти как при использовании WHERE IN («Оксфорд», «Джайлз»), но вместо «AND» вместо «AND» быть ORed?

Я не знаю, смогу ли я достичь этого? Я пробовал различные подзапросы без успеха

Я использую SQL Server 2008

Я хотел бы избежать создания полнотекстового поиска

Любые указатели для очистки тумана были бы очень полезны.

* Обновлена ​​основная запись, чтобы избежать путаницы *
Единственная связь между двумя таблицами - это идентификатор записи

** Обновлено ** 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') 

Это ничего не возвращает.

Мне это нужно, чтобы ТОЛЬКО вернуть ОСНОВНУЮ запись, в которой есть ОБА Сэмюэль И Уильям, т.е. когда поисковый термин содержит более одного имени.
Также нужно найти Уильяма Сэмюэля, а также Сэмюэля Уильяма.

Из сообщений других, я пошел по пути DIVISION и придумал следующее (помещая некоторые манипуляции со строками перед основным SELECT):

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 ('''+@Forename +''') ' +
' 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' - очень помогли

Ответы [ 5 ]

5 голосов
/ 29 октября 2010
SELECT  *
FROM    mainrecord mr
WHERE   (
        SELECT  COUNT(*)
        FROM    placenames pn
        WHERE   pn.record = mr.record
                AND pn.placename IN ('Oxford', 'St', 'Giles')
        ) = 3
2 голосов
/ 29 октября 2010

Вы имеете в виду реляционное деление ? например поставщик, который поставляет всю продукцию, пилот, который может управлять всеми самолетами в вешалке и т. д.

Если это так, эта статья имеет много примеров реализации в 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
                   );
1 голос
/ 29 октября 2010

не совсем уверен в вашей среде, но в Oracle это должно работать.

select * from mainrecord
where placename like '%Oxford%'
INTERSECT
select * from mainrecord
where placename like '%Giles%'
0 голосов
/ 29 октября 2010

Если это все, что вам нужно, вы можете использовать LIKE

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

Если вам нужно немного больше гибкости (например, ограничение соответствия целым словам), вы можете добавить поиск Regex в SQL Server легко

    SELECT PlaceName FROM PlaceNames WHERE dbo.RegExMatch(PlaceName,'\bOxford\b') = 1 
AND dbo.RegExMatch(PlaceName,'\bGiles\b') = 1
0 голосов
/ 29 октября 2010

Используйте оператор LIKE следующим образом:

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

При использовании этого запроса вам не понадобится вторая таблица, все будет выполнено через первую

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...