С таким количеством строк я могу дать вам только один совет: изменить дизайн.Каждая часть имени должна находиться в отдельном столбце ...
Следующее будет работать, но я обещаю, что это будет медленно ...
- установить тестовую базу данных
USE master;
GO
CREATE DATABASE shnugo;
GO
USE shnugo;
GO
- в вашу таблицу я добавил ID-столбец
create table tbl_pat_soundex
(
ID INT IDENTITY --needed to distinguish rows
,col_str varchar(max)
);
GO
- функция, которая будет возвращать разделенную пробелом строку в виде отсортированного по алфавиту списка различных значений soundex, разделенных /
: «Смит А Стив» возвращается как /A000/S310/S530/
CREATE FUNCTION dbo.ComputeSoundex(@str VARCHAR(MAX))
RETURNS VARCHAR(MAX)
AS
BEGIN
DECLARE @tmpXML XML=CAST('<x>' + REPLACE((SELECT @str AS [*] FOR XML PATH('')),' ','</x><x>') + '</x>' AS XML);
RETURN (SELECT DISTINCT '/' + SOUNDEX(x.value('text()[1]','varchar(max)')) AS [se]
FROM @tmpXML.nodes('/x[text()]') A(x)
ORDER BY se
FOR XML PATH(''),TYPE).value('.','nvarchar(max)') + '/';
END
GO
- Добавить столбец для постоянного хранения вычисленной цепочки звуков:
ALTER TABLE tbl_pat_soundex ADD SortedSoundExPattern VARCHAR(MAX);
GO
- Нам нужентриггер для сохранения вычисленной цепочки звуков при любой вставке или обновлении
CREATE TRIGGER RefreshComputeSoundex ON tbl_pat_soundex
FOR INSERT,UPDATE
AS
BEGIN
UPDATE s SET SortedSoundExPattern=dbo.ComputeSoundex(i.col_str)
FROM tbl_pat_soundex s
INNER JOIN inserted i ON s.ID=i.ID;
END
GO
- тестовые данные
insert into tbl_pat_soundex(col_str) values
('Smith A Steve')
,('Steve A Smyth')
,('A Smeeth Stive')
,('Steve Smith A')
,('Smit Steve A')
,('Smit Steve') --no A
,('Smit A') --no Steve
,('Smit Smith Robert Peter A') --add noise
,('Shnugo'); --something else entirely
- проверка промежуточного результата
SELECT *
FROM tbl_pat_soundex
/*
+----+---------------------------+-----------------------+
| ID | col_str | SortedSoundExPattern |
+----+---------------------------+-----------------------+
| 1 | Smith A Steve | /A000/S310/S530/ |
+----+---------------------------+-----------------------+
| 2 | Steve A Smyth | /A000/S310/S530/ |
+----+---------------------------+-----------------------+
| 3 | A Smeeth Stive | /A000/S310/S530/ |
+----+---------------------------+-----------------------+
| 4 | Steve Smith A | /A000/S310/S530/ |
+----+---------------------------+-----------------------+
| 5 | Smit Steve A | /A000/S310/S530/ |
+----+---------------------------+-----------------------+
| 6 | Smit Steve | /S310/S530/ |
+----+---------------------------+-----------------------+
| 7 | Smit A | /A000/S530/ |
+----+---------------------------+-----------------------+
| 8 | Smit Smith Robert Peter A | /A000/P360/R163/S530/ |
+----+---------------------------+-----------------------+
| 9 | Shnugo | /S520/ |
+----+---------------------------+-----------------------+
*/
- Теперь мы можем начать поиск:
DECLARE @StringToSearch VARCHAR(MAX)=' A Steve';
WITH SplittedSearchString AS
(
SELECT soundexCode.value('text()[1]','nvarchar(max)') AS SoundExCode
FROM (SELECT CAST('<x>' + REPLACE(dbo.ComputeSoundex(@StringToSearch),'/','</x><x>') + '</x>' AS XML)) A(x)
CROSS APPLY x.nodes('/x[text()]') B(soundexCode)
)
SELECT a.ID,col_str
FROM tbl_pat_soundex a
INNER JOIN SplittedSearchString s On SortedSoundExPattern LIKE '%/' + s.SoundExCode + '/%'
GROUP BY ID,col_str
HAVING COUNT(ID)=(SELECT COUNT(*) FROM SplittedSearchString)
ORDER BY ID
GO
- очистка
USE master;
GO
DROP DATABASE shnugo;
Краткое объяснение
Вот как это работает:
- Эта команда будет использовать ту же функцию для возврата soundex-цепочки всех фрагментов ввода
- Затем запрос
INNER JOIN
выполнит тест с LIKE
- это будетe sloooooow ... - Последняя проверка заключается в том, совпадает ли количество попаданий с количеством фрагментов.
И последний совет: если вы хотите найти точное совпадение, но хотите включить разные записи, вы можете просто напрямую сравнить две строки.Вы можете даже поместить индекс в новый столбец SortedSoundExPattern
.Благодаря способу создания все виды «Стивен А Смит», «Стивен А Смит» и даже в различном порядке, как «Смит Стивен А», будут производить точно такой же шаблон.