Как запросить базу данных SQL Server 2008 для имени и фамилии и порядка по релевантности? - PullRequest
5 голосов
/ 05 марта 2010

В основном у меня есть такая таблица:

CREATE TABLE Person(
    PersonID int IDENTITY(1,1) NOT NULL,
    FirstName nvarchar(512) NOT NULL,
    LastName nvarchar(512) NULL
)

И мне нужно найти лучшие n результаты, основанные на запросе пользователя, подобном этому:

"Joh Smi"

Следующий запрос возвращает результаты, которые мне нужны (я думаю). Только не в соответствующем порядке.

SELECT
    PersonID, FirstName, LastName
FROM
    Person
WHERE
    FirstName LIKE 'Joh%' OR
    LastName LIKE 'Joh%' OR
    FirstName LIKE 'Smi%' OR
    LastName LIKE 'Smi%'

Если в базе данных были указаны следующие имена и наш пользовательский запрос был "Joh Smi", имена должны появляться в следующем порядке (или аналогично)

  1. Джон Смит
  2. Джонни Смит
  3. Джон Джейкоб
  4. Дэвид Смитсониан
  5. Даниэль Джонсон

Я надеюсь заставить его работать аналогично автозаполнению поиска друзей в Facebook.

Итак, как мне вернуть n самых важных строк в SQL Server 2008?

Ответы [ 3 ]

5 голосов
/ 05 марта 2010

Я рекомендую реализовать полнотекстовый поиск (FTS) по двум причинам:

  1. Упростите запрос (не нужно OR, который будет работать плохо)
  2. Использование функции ранжирования FTS - см. эту статью
2 голосов
/ 05 марта 2010

В качестве дополнения к OMG Ponies ответьте ...

Чтобы получить наилучшие результаты полнотекстового поиска, вы можете создать индексированное представление, объединяющее поля имени и фамилии.

Это позволит вам более точно взвешивать отдельные части полного имени.

Пример кода следующий:

    CREATE VIEW [dbo].[vFullname] WITH SCHEMABINDING AS
    SELECT personID, FirstName + ' ' + LastName AS name 
    FROM dbo.person 

    WITH ranks AS(
    SELECT FT_TBL.personid 
        ,FT_TBL.name
        ,KEY_TBL.RANK
    FROM dbo.vfullname AS FT_TBL 
        INNER JOIN CONTAINSTABLE(vfullname, (name),
    'ISABOUT ("Smith" WEIGHT (0.4), "Smi*" WEIGHT (0.2),
"John" WEIGHT (0.3), "Joh*" WEIGHT (0.1))') AS KEY_TBL  
          ON FT_TBL.personid = KEY_TBL.[KEY]
    ) 
    SELECT
    r.personID,
    p.firstname,
    p.lastname,
    r.rank
    FROM ranks r INNER JOIN
    person p ON r.personID = p.personID
    ORDER BY rank DESC;

CTE позволяет вам возвращать отдельные поля имени и фамилии. Если они не нужны в качестве выходных данных, игнорируйте их.

1 голос
/ 05 марта 2010

Сначала вам нужно решить, что вы подразумеваете под релевантностью. Вот мой список релевантности

  1. Оба слова в точности совпадают с именем и фамилией
  2. То же, что в первом порядке, но в обратном порядке
  3. Один - полное слово, один - подстрока
  4. То же, что 3-й
  5. Обе подстроки. Внутри этого вы можете оценить по длине подстроки (больше значит хорошо)
  6. Одна подстрока

Поэтому я бы порекомендовал вам создать функцию, которая будет принимать FirstName и LastName, а также вводить строку и возвращать int или float в соответствии с правилами, а затем сортировать по нему.

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