2010-01-13 4 views
3

Я ищу хорошее решение для использования сдерживаемой функции SQL Serve r2005 effectivly. В настоящее время у меня есть, например. таблицу Employee и адрес.SQL Server 2005 Полнотекстовый поиск по нескольким таблицам и столбцам

-Employee 
Id 
Name 

-Address 
Id 
Street 
City 
EmployeeId 

Теперь пользователь может ввести условия поиска только один текстовое поле, и я хочу это термины должны быть разделены и поиска с «И» оператора. FREETEXTTABLE работает с «ИЛИ» автоматически.

Теперь можно сказать, что пользователь вошел в «Джон Гамбург». Это означает, что он хочет найти Джона в Гамбурге. Итак, это «Джон И Гамбург».

Таким образом, следующее не будет содержать никаких результатов, поскольку CONTAINSTABLE проверяет каждый столбец для «John AND Hamburg».

Итак, мой вопрос: что является наилучшим способом выполнения полнотекстового поиска с операторами ИСО через несколько столбцов/таблиц?

SELECT * 
FROM Employee emp 
    INNER JOIN 
     CONTAINSTABLE(Employee, *, '(JOHN AND Hamburg)', 1000) AS keyTblSp 
     ON sp.ServiceProviderId = keyTblSp.[KEY]  
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId 
UNION ALL 
SELECT * 
FROM Employee emp 
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId 
    INNER JOIN 
     CONTAINSTABLE([Address], *, '(JOHN AND Hamburg)', 1000) AS keyTblAddr 
     ON addr.AddressId = keyTblAddr.[KEY]  

... 

ответ

2

У меня была та же проблема. Вот мое решение, которое сработало для моего дела:

Я создал представление, которое возвращает нужные мне столбцы. Я добавил еще один дополнительный столбец, который объединяет все столбцы, которые я хочу искать. Таким образом, в этом случае вид будет выглядеть как

SELECT emp.*, addr.*, ISNULL(emp.Name,'') + ' ' + ISNULL(addr.City, '') AS SearchResult 
FROM Employee emp 
    LEFT OUTER JOIN [Address] addr ON addr.EmployeeId = emp.EmployeeId 

После этого я создал полнотекстовый индекс в столбце SearchResult. Затем я ищу по этой колонке

SELECT * 
FROM vEmpAddr ea 
INNER JOIN CONTAINSTABLE(vEmpAddr, *, 'John AND Hamburg') a ON ea.ID = a.[Key] 
6

Это больше проблема синтаксиса. Как вы угадываете намерение пользователя только одним полем ввода?

  • Ищем «Джон Гамбург» человека?
  • Ищете «Джона Гамбург-стрит»?
  • Они ищут «Джона», который живет на «Гамбург-стрит» в Спрингфилде?
  • Они ищут «Джона», который живет в городе «Гамбург»?

Не зная намерений пользователя, лучшее, на что вы можете надеяться, - это ИЛИ с условиями, а также получать наивысшие рейтинги.

В противном случае, вам нужно запрограммировать в тонне логики, в зависимости от количества слов прошло в:

2 слова:

данных Поиск сотрудников на срок 1, данные Поиск сотрудников на срок 2, Поиск Адресные данные для термина 1, Данные поискового адреса для термина 2. Слияние результатов по срокам, порядок по большинству обращений.

3 слова:

данных Поиск сотрудников на срок 1, данные Поиск сотрудников на срок 2, данные поиска сотрудника на срок 3, адресный поиск данных для термина 1, адресный поиск данных для терм 2, поиск адреса для срок 3. Слияние результатов по срокам, порядок по большинству просмотров.

и т.д ...

Я думаю, я бы перепроектировать GUI, чтобы отделить вклад в имя и адрес, как минимум. Если это не представляется возможным, применить правило синтаксиса для эффекта «Первые слова будут считаться имя до тех пор, пока не появится запятая, любые слова, после этого будут рассмотрены адреса»

EDIT:

Ваш лучший выбор по-прежнему OR или термины, и берут наивысшие рейтинги.Вот пример того, что и пример, почему это не идеал без какой-либо предварительной обработки входных данных предугадывать намерения пользователя:

insert into Employee (id, [name]) values (1, 'John Hamburg') 
insert into Employee (id, [name]) values (2, 'John Smith') 
insert into Employee (id, [name]) values (3, 'Bob Hamburg') 
insert into Employee (id, [name]) values (4, 'Bob Smith') 
insert into Employee (id, [name]) values (5, 'John Doe') 

insert into Address (id, street, city, employeeid) values (1, 'Main St.', 'Springville', 1) 
insert into Address (id, street, city, employeeid) values (2, 'Hamburg St.', 'Springville', 2) 
insert into Address (id, street, city, employeeid) values (3, 'St. John Ave.', 'Springville', 3) 
insert into Address (id, street, city, employeeid) values (4, '5th Ave.', 'Hamburg', 4) 
insert into Address (id, street, city, employeeid) values (5, 'Oak Lane', 'Hamburg', 5) 

Теперь, так как мы не знаем, какие ключевые слова будут применяться к какой таблице, мы должны предположить, что они могут применяться к любой из таблиц, поэтому мы должны использовать OR для каждой таблицы, UNION - результаты, сводить их и вычислять самый высокий ранг.

SELECT Id, [Name], Street, City, SUM([Rank]) 
FROM 
(
    SELECT emp.Id, [Name], Street, City, [Rank] 
    FROM Employee emp 
    JOIN [Address] addr ON emp.Id = addr.EmployeeId 
    JOIN CONTAINSTABLE(Employee, *, 'JOHN OR Hamburg') AS keyTblEmp ON emp.Id = keyTblEmp.[KEY] 

    UNION ALL 

    SELECT emp.Id, [Name], Street, City, [Rank] 
    FROM Employee emp 
    JOIN [Address] addr ON emp.Id = addr.EmployeeId 
    JOIN CONTAINSTABLE([Address], *, 'JOHN OR Hamburg') AS keyTblAdd ON addr.Id = keyTblAdd.[KEY] 
) as tmp 

GROUP BY Id, [Name], Street, City 
ORDER BY SUM([Rank]) DESC 

Это меньше, чем идеал, вот что вы получите для примера (в вашем случае, вы бы хотели John Doe из Гамбурга, чтобы показать первый):

Id  Name    Street   City   Rank 
2  John Smith  Hamburg St.  Springville 112 
3  Bob Hamburg  St. John Ave.  Springville 112 
5  John Doe   Oak Lane   Hamburg  96 
1  John Hamburg  Main St.   Springville 48 
4  Bob Smith   5th Ave.   Hamburg  48 

Но это лучшее, что вы можете сделать, не анализируя входные данные перед отправкой его на SQL, чтобы сделать «лучшее предположение» по желанию пользователя.

+1

Спасибо за ваш ответ. Я хочу сохранить один поле ввода, потому что пользователю будет легко искать что-то реальное, как в Google. Если пользователь ищет John Hamburg, он хочет получить результаты для John, который, например, живет в Hamburg John whos lastname может быть Hamburg, а также, может быть, он живет в Hamburg Но ничего не найдено для Just John, который не живет в Hamburg Гамбург. Или другой человек, который живет в Гамбурге. Дело в том, что в дальнейшем более подробная информация будет доступна для поиска, например, E-Mails и т. Д. Поэтому мне нужно сдерживать все данные одновременно с терминами, которые связаны с AND. – Chris

+0

Что возвращается к синтаксису. Если вы не знаете, в какой таблице и столбце должно применяться ключевое слово ввода, вы не можете создать инструкцию «один размер-подходит для всех» AND без программирования в тонне логики. В вашем случае выше, как вы знаете, чтобы искать первое ключевое слово как [Имя], а второе ключевое слово - как [Город]? Что делать, если пользователь хотел, чтобы второе ключевое слово было частью имени или части улицы? Если у вас нет некоторых синтаксических правил, о которых вы не упомянули, что говорит что-то, что «Первое слово будет именем, второе слово будет городом»? – GalacticJello

+0

@ Крис Всякий раз, когда я вижу фразу «как в Google», мой ответ всегда один и тот же: если создать логику «как в Google» было достаточно легко ответить на stackoverflow, они не использовали бы тысячи высокооплачиваемых разработчиков. Не ожидайте, что сможете воспроизвести такое качество всего за несколько дней. – ean5533