SQL Server: найти процентное соответствие строки LIKE

Я пытаюсь написать запрос, чтобы найти процентное совпадение строки поиска в примечаниях или столбце TEXT.

Вот с чего я начинаю:

SELECT * 
FROM NOTES 
WHERE UPPER(NARRATIVE) LIKE 'PAID CALLED RECEIVED'

В конечном счете, я хочу сделать следующее:

  1. Разделите строку поиска на пробелы и ищите по отдельности все слова в строке.
  2. Упорядочить результаты по убыванию на основе процентного совпадения

Например, в приведенном выше сценарии каждое слово в строке поиска будет составлять 33,333% от общего числа. NARRATIVE с 3 совпадениями (100%) должно быть вверху результатов, в то время как соответствие, содержащее 2 ключевых слова (66,666 %), будет ниже, а соответствие, содержащее 1 ключевое слово (33,333 %), будет еще ниже. .

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

Надеюсь, это имеет смысл и может быть сделано. Любые мысли о том, как действовать? Все это ДОЛЖНО быть выполнено в SQL Server, и я бы предпочел не писать никаких CTE.

Заранее благодарим вас за любое руководство.


person sadmicrowave    schedule 13.08.2014    source источник
comment
Очень похоже на этот вопрос title="можно ли сравнивать строки для похожих данных на сервере sql">stackoverflow.com/questions/18836884/, который я разместил для некоторых UDF, которые я преобразовал из кода VB, чтобы сделать именно это.   -  person Steve    schedule 14.08.2014
comment
похоже, вы захотите узнать о полнотекстовом поиске. У него есть функции CONTAINS и CONTAINSTABLE, возможно, вам придется использовать условие ISABOUT вместе с опцией weight(), вот так ... WHERE CONTAINS(NARRATIVE, 'ISABOUT (PAID weight(0.333), CALLED weight(0.333), RECEIVED weight(0.333))'), ... Я даже мало использовал эту функцию.   -  person King King    schedule 14.08.2014
comment
Альтернатива... взгляните на запросы расстояния Левенштейна (google mssql Levenshtein)   -  person Twelfth    schedule 14.08.2014
comment
@Twelfth Я не могу использовать CONTAINS ИЛИ FREETEXT, потому что в этом поле/таблице нет произвольного текстового индекса, и у меня нет прав на его добавление.   -  person sadmicrowave    schedule 14.08.2014


Ответы (2)


Вот что я придумал:

DECLARE @VISIT VARCHAR(25) = '999232'
DECLARE @KEYWORD VARCHAR(100) = 'PAID,CALLED,RECEIVED'

DECLARE SPLIT_CURSOR CURSOR FOR
SELECT RTRIM(LTRIM(VALUE)) FROM Rpt_Split(@KEYWORD, ',')

IF OBJECT_ID('tempdb..#NOTES_FF_SEARCH') IS NOT NULL DROP TABLE #NOTES_FF_SEARCH

SELECT   N.VISIT_NO
    ,N.CREATE_DATE
    ,N.CREATE_BY
    ,N.NARRATIVE
    ,0E8 AS PERCENTAGE
INTO #NOTES_FF_SEARCH
FROM NOTES_FF AS N
WHERE   N.VISIT_NO = @VISIT

DECLARE @KEYWORD_VALUE AS VARCHAR(255)

OPEN SPLIT_CURSOR
FETCH NEXT FROM SPLIT_CURSOR INTO @KEYWORD_VALUE

WHILE @@FETCH_STATUS = 0
BEGIN
    UPDATE #NOTES_FF_SEARCH
        SET PERCENTAGE = PERCENTAGE + ( 100 / @@CURSOR_ROWS )
    WHERE UPPER(NARRATIVE) LIKE '%' + UPPER(@KEYWORD_VALUE) + '%'

    FETCH NEXT FROM SPLIT_CURSOR INTO @KEYWORD_VALUE
END

CLOSE SPLIT_CURSOR
DEALLOCATE SPLIT_CURSOR


SELECT * FROM #NOTES_FF_SEARCH
WHERE PERCENTAGE > 0
ORDER BY PERCENTAGE, CREATE_DATE DESC

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

person sadmicrowave    schedule 14.08.2014
comment
это круто - person ViKiNG; 17.05.2017
comment
Спасибо за это! Помогаем людям почти 5 лет спустя! - person Spasticmonkey; 13.06.2019

Если вы хотите выполнить «процентное» совпадение, вам нужно сделать две вещи: вычислить количество слов в строке и вычислить количество слов, которые вас интересуют. Прежде чем дать некоторые рекомендации, я скажу, что полнотекстовый поиск, вероятно, делает все, что вам нужно, и намного эффективнее.

Предполагая, что в строке поиска есть слова, разделенные пробелами, вы можете подсчитать слова с помощью выражения:

(len(narrative) - len(replace(narrative, ' ', '') + 1) as NumWords

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

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

select n.*
from (select n.*,
             (len(narrative) - len(replace(narrative, ' ', '') + 1.0) as NumWords,
             ltrim(rtrim(replace(replace(replace(narrative + ' ', @keyword1 + ' ', ''),
                                         @keyword2 + ' ', ''), 
                                  @keyword3 + ' ', ''))) as NoKeywords
      from notes n
     ) n
order by 1 - (len(NoKeywords) - len(replace(NoKeywords, ' ', '') + 1.0)  / NumWords desc;

SQL Server, как и многие другие базы данных, не очень хорошо разбирает строки. Вы можете сделать это вне запроса и соответствующим образом назначить переменные @keyword.

person Gordon Linoff    schedule 13.08.2014