Нечеткое соответствие SQL

Надеюсь, я не повторяю этот вопрос. Я сделал поиск здесь и google перед публикацией здесь.

Я запускаю eStore с SQL Server 2008R2 с включенным полным текстом.

Мои требования,

  • Существует таблица продуктов, в которой есть название продукта, коды OEM, модель, в которую входит этот продукт. Все в тексте.
  • Я создал новый столбец TextSearch. Это имеет объединенные значения Название продукта, OEM-код и модель, в которые входит этот продукт. Эти значения разделяются запятой.
  • Когда клиент вводит ключевое слово, мы запускаем поиск в столбце TextSearch для соответствия продуктам. См. Соответствующую логику ниже.

Я использую Hybrid Fulltext и обычно люблю делать поиск. Это дает более релевантные результаты. Все запросы, выполненные в таблицу temp и отдельные элементы, были возвращены.

Логика соответствия,

  • Запустите следующий SQL, чтобы получить соответствующий продукт, используя полный текст. Но @Keywords будут предварительно обработаны. Скажем, CLC 2200 будет изменен на 'CLC * AND 2200 *'

    SELECT Id FROM dbo.Product WHERE CONTAINS (TextSearch, @Keywords)

  • Другой запрос будет выполняться с использованием обычного типа. Таким образом, CLC 2200 будет предварительно обработан в TextSearch, например,% clc% AND TextSearch, например% 2200%. Это просто потому, что полнотекстовый поиск не будет искать шаблоны перед ключевыми словами. Например, он не вернет "pclc 2200".

    SELECT Id FROM dbo.Product WHERE TextSearch, например "% clc%" и "TextSearch", например "% 2200%"

  • Если шаги 1 и 2 не вернули записи, будет выполнен следующий поиск. Значение 135 было настроено мной, чтобы вернуть более релевантные записи.

    SELECT p.id FROM dbo.Product AS p INNER JOIN FREETEXTTABLE (продукт, TextSearch, @Keywords) AS r ON p.Id = r. [KEY] WHERE r.RANK > 135

Все вышеперечисленные комбинированные работы отлично работают с разумной скоростью и возвращают соответствующие продукты для ключевых слов.

Но я ищу для дальнейшего улучшения, когда продукта нет.

Скажем, если клиент ищет "CLC 2200npk" , и этого продукта там не было, мне нужно было показать рядом очень близко "CLC 2200" .

До сих пор я пытался использовать функцию Soundex(). Купите значение soundex для каждого слова в столбце TextSearch и сравнивайте его с значением судекса ключевого слова. Но это возвращает слишком много записей и замедляет работу.

Например, "CLC 2200npk" вернет такие продукты, как "CLC 1100" и т.д. Но это не будет хорошим результатом. Поскольку он не близок к CLC 2200npk

Здесь есть еще одна хорошая . но это использует функции CLR. Но я не могу установить CLR-функции на сервере.

Итак, моя логика должна быть,

если "CLC 2200npk" не найден, нажмите "CLC 2200" , если "CLC 2200" не найден, рядом с ним следует "CLC 1100"

Вопросы

  • Возможно ли совпадение, как предлагается?
  • Если мне понадобится исправление орфографии и поиск, что было бы хорошим способом? Весь наш список продуктов находится на английском языке.
  • Есть ли UDF или SP для соответствия текстам, например, моим предложениям?

Спасибо.

Ответ 1

Скорее быстрое решение для конкретного домена может заключаться в вычислении сходства строк с использованием SOUNDEX и числового расстояния между двумя строками. Это действительно поможет, когда у вас будет много кодов продуктов.

Используя простой UDF, как показано ниже, вы можете извлечь числовые символы из строки, чтобы затем получить 2200 из "CLC 2200npk" и 1100 из "CLC 1100", чтобы теперь можно было определить близость на основе вывода SOUNDEX каждого входа, а также близость числовой составляющей каждого входа.

CREATE Function [dbo].[ExtractNumeric](@input VARCHAR(1000))
RETURNS INT
AS
BEGIN
    WHILE PATINDEX('%[^0-9]%', @input) > 0
    BEGIN
        SET @input = STUFF(@input, PATINDEX('%[^0-9]%', @input), 1, '')
    END
    IF @input = '' OR @input IS NULL
        SET @input = '0'
    RETURN CAST(@input AS INT)
END
GO

Что касается алгоритмов общего назначения, то есть пара, которая может помочь вам с разной степенью успеха в зависимости от размера набора данных и требований к производительности. (обе ссылки имеют реализацию TSQL)

  • Двойной метафон - Этот алгоритм даст вам лучшее совпадение, чем soundex за счет скорости, но это действительно хорошо для коррекции орфографии.
  • Расстояние Левенштейна - это будет подсчитывать, сколько нажатий клавиши, чтобы перевести одну строку в другую, например, для перехода с CLC 2200npk на 'CLC 2200' 3, а от "CLC 2200npk" до "CLC 1100" - 5.

Здесь - интересная статья, в которой используются оба альгоса, которые могут дать вам несколько идей.

Ну, надеюсь, некоторые из них немного помогают.

EDIT: Здесь - это намного более быстрая частичная реализация Levenshtein Distance (прочитайте сообщение, которое он не вернет точно так же, как и обычный). В моей тестовой таблице из 125000 строк она работает через 6 секунд по сравнению с 60 секундами для первой, с которой я связан.