Здравствуйте,помогите пожалуйста советом!Необходимо сравнить две таблицы и найти в них совпадения включая опечатки.
Фамилии, которые нужно сравнить находятся в таблице
zags(количество записей 1600).
Фамилии с которыми нужно сравнить находятся в таблице
WM_PERSONAL_CARD (количество записей более 120000).
Функция
uf_distance была найдена на данном форуме, далее к ней был дописан курсор для поиска совпадений.
Быстродействие данного курсора катастрофически мала,на поиски одного человека уходит 2 минуты.
Помогите люди добрые как оптимизировать данный алгоритм!)
Заранее спасибо!
--Функция расчета кол-ва несовпадения символов
CREATE FUNCTION [dbo].[uf_distance](@s1 nvarchar(3999), @s2 nvarchar(3999))
RETURNS int
AS
BEGIN
DECLARE @s1_len int, @s2_len int, @i int, @j int, @s1_char nchar, @c int, @c_temp int,
@cv0 varbinary(8000), @cv1 varbinary(8000)
SELECT @s1_len = LEN(@s1), @s2_len = LEN(@s2), @cv1 = 0x0000, @j = 1, @i = 1, @c = 0
WHILE @j <= @s2_len
SELECT @cv1 = @cv1 + CAST(@j AS binary(2)), @j = @j + 1
WHILE @i <= @s1_len
BEGIN
SELECT @s1_char = SUBSTRING(@s1, @i, 1), @c = @i, @cv0 = CAST(@i AS binary(2)), @j = 1
WHILE @j <= @s2_len
BEGIN
SET @c = @c + 1
SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j-1, 2) AS int) +
CASE WHEN @s1_char = SUBSTRING(@s2, @j, 1) THEN 0 ELSE 1 END
IF @c > @c_temp SET @c = @c_temp
SET @c_temp = CAST(SUBSTRING(@cv1, @j+@j+1, 2) AS int)+1
IF @c > @c_temp SET @c = @c_temp
SELECT @cv0 = @cv0 + CAST(@c AS binary(2)), @j = @j + 1
END
SELECT @cv1 = @cv0, @i = @i + 1
END
RETURN @c
END
--- Процедура сравнения
delete from KNN_KONTR_SIMWOL_ZAGS -- таблица результатов
declare @nOuid int,
@nOuid1 int,
@sFio varchar(100),
@sFio1 varchar(100),
@sDtr varchar(10),
@sDtr1 varchar(10),
@nKolSimw int,
@sStr1 varchar(255),
@sStr2 varchar(255)
-- Идентификатор табл., ФИ, Дата рожд.
select OUID_Z,rtrim(Family)+' '+rtrim(Name)+' '+convert(varchar(10),datr,104) from zags -- Список ЛД, которые надо сравнить (1600 чел)
where datr is not null
order by OUID_Z
OPEN curSpisLD1
FETCH NEXT FROM curSpisLD1 INTO @nOuid, @sStr1
WHILE @@fetch_status = 0
BEGIN
DECLARE curSpisLD INSENSITIVE CURSOR FOR
-- Идентификатор табл., ФИ, Дата рожд.
SELECT WM_PERSONAL_CARD.ouid ,
rtrim(SPR_FIO_SURNAME.A_NAME)+' '+rtrim(SPR_FIO_NAME.A_NAME)+' '+convert(varchar(10),WM_PERSONAL_CARD.BIRTHDATE,104) -- Дата рождения
from WM_PERSONAL_CARD -- Список ЛД с которыми надо сравнить т(120000 чел.)
INNER JOIN SPR_FIO_SURNAME ON WM_PERSONAL_CARD.SURNAME= SPR_FIO_SURNAME.OUID -- фамилия
INNER JOIN SPR_FIO_NAME ON SPR_FIO_NAME.OUID = WM_PERSONAL_CARD.A_NAME -- имя
where isnull(WM_PERSONAL_CARD.a_status,0) in (0,10)
and WM_PERSONAL_CARD.a_pcstatus=1
order by 2
OPEN curSpisLD
FETCH NEXT FROM curSpisLD INTO @nOuid1, @sFio1
WHILE @@fetch_status = 0
BEGIN
select @nKolSimw =dbo.uf_distance(@sStr1, @sFio1) -- кол-во несовпадающих символов
if @nKolSimw <5
insert into KNN_KONTR_SIMWOL_ZAGS (OUID_Z, OUID_LD, KOL_SIMW)
select @nOuid, @nOuid1, @nKolSimw
FETCH NEXT FROM curSpisLD INTO @nOuid1, @sFio1
END
CLOSE curSpisLD
DEALLOCATE curSpisLD
FETCH NEXT FROM curSpisLD1 INTO @nOuid, @sStr1
END
CLOSE curSpisLD1
DEALLOCATE curSpisLD1