Вот решение с использованием рекурсивных 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.