Поиск поля varchar, которое содержит все слова из другой строки - PullRequest
4 голосов
/ 18 ноября 2010

пытается выполнить небольшую хранимую процедуру, не добавляя индексацию свободного текста только для этого (SQL Server 2008)

По сути, я хочу найти все записи, где определенное поле содержит все слова из параметра.

Так что, если в поле у ​​меня есть «Это тестовое поле», и параметром для моего SP будет «это тестовое поле», он вернет его, как если бы параметр был «поле этого теста»".

Таблица очень маленькая (4000) записей и нагрузка будет низкой, поэтому эффективность не имеет большого значения.Прямо сейчас единственное решение, о котором я могу подумать, это разделить обе строки с помощью табличной функции и перейти оттуда.

Любая более простая идея?

Спасибо!

Ответы [ 2 ]

2 голосов
/ 18 ноября 2010

Если эффективность не является большой проблемой, почему бы не пойти с небольшим количеством динамического SQL. Что-то вроде:

create procedure myproc (@var varchar(100))
as
set @var = '%' + replace(@var, ' ', '%') + '%'
exec ('select * from mytable where myfield like '''+ @var + '''')
1 голос
/ 18 ноября 2010

Вот решение с использованием рекурсивных CTE.Это на самом деле использует две отдельные рекурсии.Первый разбивает строки на токены, а второй рекурсивно фильтрует записи, используя каждый токен.

declare     
    @searchString varchar(max),
    @delimiter char;

select 
@searchString  = 'This is a test field'
,@delimiter = ' '

declare @tokens table(pos int, string varchar(max))

 ;WITH Tokens(pos, start, stop) AS (
      SELECT 1, 1, CONVERT(int, CHARINDEX(@delimiter, @searchString))
      UNION ALL
      SELECT pos + 1, stop + 1, CONVERT(int, CHARINDEX(@delimiter, @searchString, stop + 1))
      FROM Tokens
      WHERE stop > 0
    )
    INSERT INTO @tokens
    SELECT pos,
      SUBSTRING(@searchString, start, CASE WHEN stop > 0 THEN stop-start ELSE 512 END) AS string
    FROM Tokens
    OPTION (MAXRECURSION 25000) ;

;with filter(ind, myfield) as (
    select  1,myfield from mytable where myfield like '%'+(select string from @tokens where pos = 1)+'%'    
    union all
    select  ind + 1, myfield from filter where myfield like '%'+(select string from @tokens where pos = ind + 1)+'%'    
    )

    select * from filter where ind = (select COUNT(1) from @tokens)

У меня заняло около 15 секунд, чтобы найти в таблице из 10 тыс. Записей строку поиска «это тестовое поле» .. (чем больше слов в строке, тем больше времени занимает ..)

Редактировать
Если вы хотите нечеткий поиск, то есть возвращать близко совпадающие результаты, даже если не было точного совпадения, вы можете изменить последнюю строку в запросе так:select * from (select max(ind) as ind, myfield from filter group by myfield) t order by ind desc

'ind' даст вам количество слов из строки поиска, найденной в myfield.

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