powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Поиск дубликатов по схожести
15 сообщений из 15, страница 1 из 1
Поиск дубликатов по схожести
    #35227915
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Предлагаю мой вариант решения проблемы дубликатов.

Пользователю представляются на рассмотрение пары (строка, потенциальный дубликат). Для каждой пары пользователь может нажать кнопку: "справа дубликат", или "слева дубликат".

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

Если для каждой строки выбрать начинающиеся на ту же букву - будет ~30000 пар - все еще очень много.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
declare @tBrand table (ID int identity( 1 , 1 ) not null primary key, Title nvarchar( 50 ))
insert
 into @tBrand(Title)
select N'ALBERTO GUARDIANI' union all select N'ALBERTO GUARDIANO' union all select N'ALTHANZ'
union all select N'ALTANA' union all select N'CHLOE' union all select N'CHLOE' 
union all select N'Chao-Chao' union all select N'Chaos' union all select N'Chloe'
union all select N'Alfonso Gonsalez' union all select N'Manfrotto' union all select N'Dina Bebe'
union all select N'Diana Baby' union all select N'Chanel Coco' union all select N'Camel Cacao'
union all select N'Calvin Klein Jeans' union all select N'CALVIN KLEIN'
;

with
adapter as
(
	select
		ID as ID,
		Title as v
	from @tBrand
)
,
pairs as
(
select x.v as a, y.v as b, x.ID as aID, y.ID as bID
from adapter as x
join adapter y
on lower(left(x.v, 1 )) = lower(left(y.v, 1 ))
-- cross join adapter as y
where difference(lower(x.v), lower(y.v)) >  3  and x.ID != y.ID
)
,
intersections as
(
select distinct
	case when aID < bID then a else b end as a,
	case when aID < bID then b else a end as b,
	case when aID < bID then aID else bID end as aID,
	case when aID < bID then bID else aID end as bID
	from pairs
)
select a, b, aID, bID, difference(a,b) as similarity from intersections
union
select a, b, aID, bID,  5  as similarity from intersections where a = b
order by similarity desc, a, b
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35228720
gpПредлагаю мой вариант решения проблемы дубликатов.

Пользователю представляются на рассмотрение пары (строка, потенциальный дубликат). Для каждой пары пользователь может нажать кнопку: "справа дубликат", или "слева дубликат".

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

Если для каждой строки выбрать начинающиеся на ту же букву - будет ~30000 пар - все еще очень много.

Код: plaintext
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
declare @tBrand table (ID int identity( 1 , 1 ) not null primary key, Title nvarchar( 50 ))
insert
 into @tBrand(Title)
select N'ALBERTO GUARDIANI' union all select N'ALBERTO GUARDIANO' union all select N'ALTHANZ'
union all select N'ALTANA' union all select N'CHLOE' union all select N'CHLOE' 
union all select N'Chao-Chao' union all select N'Chaos' union all select N'Chloe'
union all select N'Alfonso Gonsalez' union all select N'Manfrotto' union all select N'Dina Bebe'
union all select N'Diana Baby' union all select N'Chanel Coco' union all select N'Camel Cacao'
union all select N'Calvin Klein Jeans' union all select N'CALVIN KLEIN'
;

with
adapter as
(
	select
		ID as ID,
		Title as v
	from @tBrand
)
,
pairs as
(
select x.v as a, y.v as b, x.ID as aID, y.ID as bID
from adapter as x
join adapter y
on lower(left(x.v, 1 )) = lower(left(y.v, 1 ))
-- cross join adapter as y
where difference(lower(x.v), lower(y.v)) >  3  and x.ID != y.ID
)
,
intersections as
(
select distinct
	case when aID < bID then a else b end as a,
	case when aID < bID then b else a end as b,
	case when aID < bID then aID else bID end as aID,
	case when aID < bID then bID else aID end as bID
	from pairs
)
select a, b, aID, bID, difference(a,b) as similarity from intersections
union
select a, b, aID, bID,  5  as similarity from intersections where a = b
order by similarity desc, a, b

Ну, не знаю... Есть же нормальные (хоть и старые) алгоритмы.
Например, SOUNDEX:
строится ХЭШ-значение для слова по определнному алгоритму. Хэш получается вида Бххх, где Б-первая буква слова, ххх - цифровой код на основании анализа согласных букв слова (все гласные пропускаются)...
Это можно оформить в функцию (хранимую процедуру) и выдавать только те записи, где Soundex(left) == Soundex(right).
Есть только одно "но": я встречал описание данного алгоритма исключительно для латиницы. Для кириллицы, ИМХО, он должен быть слегка видоизменен...
Но, судя по Вашему примеру, Вам этот алгоритм подойдет...
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35229188
Фотография Jimmy
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Здесь смотри: тынЦ
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35230848
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Результат с soundex примерно такой же как с difference, разницы я не увидел, только к тому же нету нормы, разве что считать difference(soundex(a), soundex(b))

С кирилицей вилы. Разве что транслитерировать втупую, и опять soundex / difference.

Суть была больше в интерфейсе для сопоставления.
Человек сидит, и тупо просматривает пары, нажимает одну из трех кнопок - слева дубликат, справа дубликат, вообще не дубликат
По ходу устранения дубликатов, желательно обновлять вид, чтобы не показывать пары с удаленными записями.

Вот только не понятно, как поступать при указании дубликата записи, которая сама потом окажется дубликатом?

Наверное, нужно скорее две кнопки - дубликаты - не дубликаты,
а уже после завершения просмотра, показать группы выявленных взаимных дубликатов, и потребовать указать оригинал.
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35232081
ModelR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gpРезультат с soundex примерно такой же как с difference, разницы я не увидел, только к тому же нету нормы, разве что считать soundex(a), soundex(b))
Это как раз математически принципиально. soundex(a) = soundex(b) задает отношение эквивалентности на множестве проверяемых элементов, а difference(a,b) < Limit - отношение толератности, не транзитивное.
Практически это может вести к коллизиям типа:

ABCD
ABCY
АВXD
ABXY

и сколько элементов оставлять?
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35233173
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
авторЭто как раз математически принципиально. soundex(a) = soundex(b) задает отношение эквивалентности на множестве проверяемых элементов, а difference(a,b) < Limit - отношение толератности, не транзитивное.
Практически это может вести к коллизиям типа:

ABCD
ABCY
АВXD
ABXY

и сколько элементов оставлять?

А кто говорил об эквивалентности?
Она то как раз и противопоказана.
Главное - не пытаться заставить машину делать то, что ей не противопоказано делать, а именно - принимать решения.

Как вам вот это:
select soundex('sushi') == S200
select soundex('sashimi') == S250
select soundex('susha') == S200
С отношением эквивалентности я гарантировано теряю синонимы sushi != sashimi, и получаю бредовое sushi == susha

Задача стоит не в том, чтобы машина принимала решение, а в том, чтобы свести перебор пользователем N^2 записей перебору значительно меньшего колличества, предположительно
C N ln(N).

При этом, я сортирую дубликаты в порядке злостности, для этого я использую пространство с метрикой (5 - difference(a,b) - case when lower(a)=lower(b) then 1 else 0 end), а отношение эквивалентности будет задано пользователем, уже в другом пространстве.
Вообще говоря, метрика может быть более адекватной, но это не суть.

PS
Я знаю разницу между суши и сашими :)
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35233899
ModelR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gpА кто говорил об эквивалентности?
Она то как раз и противопоказана.
Главное - не пытаться заставить машину делать то, что ей не противопоказано делать, а именно - принимать решения.
Дубликат == эквивалент: Если А дубликат Б и Б дубликат В то А дубликат В. gp Как вам вот это:
select soundex('sushi') == S200
select soundex('sashimi') == S250
select soundex('susha') == S200
С отношением эквивалентности я гарантировано теряю синонимы sushi != sashimi, и получаю бредовое sushi == sushaТеряете, ибо неподходяще выбран критерий дублирования, вот и все. gp

Задача стоит не в том, чтобы машина принимала решение, а в том, чтобы свести перебор пользователем N^2 записей перебору значительно меньшего колличества, предположительно
C N ln(N).Именно. Тупой алгоритм понимает, что это одно и тоже, но не спобен понять тонкой разницы - кого же оставить.
З.Ы. Зачем N^2 ? Чтобы действительно (N-1)*N/2 :
Код: plaintext
where difference(lower(x.v), lower(y.v)) >  3  and x.ID < y.ID
gp
При этом, я сортирую дубликаты в порядке злостности, для этого я использую пространство с метрикой (5 - difference(a,b) - case when lower(a)=lower(b) then 1 else 0 end), а отношение эквивалентности будет задано пользователем, уже в другом пространстве.
Вообще говоря, метрика может быть более адекватной, но это не суть.

PS
Я знаю разницу между суши и сашими :)
Разница как раз в объеме работы для юзера.
Если есть критерий дублирования, то юзеру (ЛПР) можно вывалить всю очередную пачку эквивалентов чтобы он выбрал один из них как правильный. При этом один элемент будет предявлен ЛПР максимум один раз. Если есть только критерий схожести, то придется идти по парам, и один элемент может быть предъявлен ЛПР несколько раз.

Типа

Комп: Берем ABCD. На него похожи ABCY и АВXD.
ЛПР: Это все разные вещи.
Комп: Берем ABCY. На него похожи ABCD (ой , ЛПР уже сказал что они разные - не буду переспрашивать), ну хорошо, а ABXY?
ЛПР: ABCY фтопку, ABXY оставить.
Комп: Берем АВXD. На него похож ABXY.
ЛПР: Это все разные вещи.
Комп: ГОТОВО.

7 предъявлений при 4х элементах.



ABXY
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35235846
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
ModelR
Комп: Берем ABCD. На него похожи ABCY и АВXD.
ЛПР: Это все разные вещи.
Комп: Берем ABCY. На него похожи ABCD (ой , ЛПР уже сказал что они разные - не буду переспрашивать), ну хорошо, а ABXY?
ЛПР: ABCY фтопку, ABXY оставить.
Комп: Берем АВXD. На него похож ABXY.
ЛПР: Это все разные вещи.
Комп: ГОТОВО.


Сдесь у Вас ошибка.
Дело в том, что с отношением эквивалентности вы не получите пары {ABCY,ABXY}
потому что из свойства транзитивности:
Из ABCY = ABXY следует ABXY = ABCD и ABXY = АВXD, тогда почему в первой строчке вы не указали ABXY?

И ошибка эта именно из за того, что отношение эквивалентности не позволяет построить такой алгоритм.
Представьте, что вы расположили точки на тетрадном листе в клетку.
Нужно найти все пары тех, что ближе полусантиметра друг от друга.
Образно говоря, то что предлагаете вы - это считать парами все, что находится в пределах одной клетки, хотя пара точек из соседних клеток может оказаться гораздо ближе друг к другу, чем точки одной клетки, что я вам и проиллюстрировал на примере (sushi sashimi susha), и в приложенной иллюстрации.

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

PS
Предложение ввести кнопку - "это все не дубликаты" - надо будет принять к сведению, спасибо.
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35236037
Так вам надо дубликаты или синонимы?

Заметьте - это разные вещи (!).

Дубликаты подразумевают, что soundex(a) = soundex(b) с учетом возможных ошибок написания со слуха (вспомните парные глухие и звонкие согласные: Б-П, Г-К, З-С, Д-Т, В-Ф и т.д.).
Например:
Дубликатами-кандидатами по soundex() будут Иванов, Иванова, Ивановы, Ивонов, Ивонв и т.д.(какие только "изумительные" ошибки не делают при вводе Фамилии, Имени, Отчества), а дальше уже пользователь выберет реальные дубликаты

Синонимы - слова близкие по смыслу, но разные по написанию. Поэтому они не будут являться дубликатами (Например, ключ - родник - источник или автомобиль - машина или компьютер-машина-ПиСюк). Здесь уже не поможет анализ слова, надо делать смысловой анализатор (aka искуственный интеллект).
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35236866
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Я автоматизирую поиск дубликатов, тоесть записей, которые в реальном мире соответствуют одной и той же сущности.

Причем здесь синонимы? Какие смысловые анализаторы? Это обычные опечатки, в основном, и родовая травма доставшейся "в наследство" базы, где можно даже создать два бренда с одинаковым названием, без разницы в регистре слов, так что теперь даже самый тривиальный уникальный индекс нельзя наложить на поле.
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35236934
ModelR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gp ModelR
Комп: Берем ABCD. На него похожи ABCY и АВXD.
ЛПР: Это все разные вещи.
Комп: Берем ABCY. На него похожи ABCD (ой , ЛПР уже сказал что они разные - не буду переспрашивать), ну хорошо, а ABXY?
ЛПР: ABCY фтопку, ABXY оставить.
Комп: Берем АВXD. На него похож ABXY.
ЛПР: Это все разные вещи.
Комп: ГОТОВО.


Сдесь у Вас ошибка.
Дело в том, что с отношением эквивалентности вы не получите пары {ABCY,ABXY}
потому что из свойства транзитивности:
Из ABCY = ABXY следует ABXY = ABCD и ABXY = АВXD, тогда почему в первой строчке вы не указали ABXY?

И ошибка эта именно из за того, что отношение эквивалентности не позволяет построить такой алгоритм.Конечно не позволяет.
Дык написано же - похожи . Т.е. это как раз не для случая эквивалентности, а для толерантности (схожести).
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35237309
drev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
1. Крайне желательно иметь следующие варианты:

- B,(C, D, E, ..) - полные дубликаты A (позволяет системе удалить B,(C, D, E, ..) и переконфигурировать ссылки)

- А и B,(C, D, E, ..) описывают один объект, но в каждом из них присутствует информация об объекте, которой нет в других

- Исключить пары из дальнейшего анализа дубликатов.

2. В случае сложных объектов часто нужно иметь возможность сравнивать не только сами объекты, но и их связи.

3. Часто нужно быть готовым к тому, что строки, использующиеся для идентификации объектов (а их может быть не одна) введены на разных языках и/или трансилитирированы

4. Нужно быть готовым, что удаление дубликатов - это перманентная активность

5. В некоторых ситуациях дубликаты могут находится в разных таблицах
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35237432
gp
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
drev1. Крайне желательно иметь следующие варианты:

- B,(C, D, E, ..) - полные дубликаты A (позволяет системе удалить B,(C, D, E, ..) и переконфигурировать ссылки)

- А и B,(C, D, E, ..) описывают один объект, но в каждом из них присутствует информация об объекте, которой нет в других

- Исключить пары из дальнейшего анализа дубликатов.

2. В случае сложных объектов часто нужно иметь возможность сравнивать не только сами объекты, но и их связи.

3. Часто нужно быть готовым к тому, что строки, использующиеся для идентификации объектов (а их может быть не одна) введены на разных языках и/или трансилитирированы

4. Нужно быть готовым, что удаление дубликатов - это перманентная активность

5. В некоторых ситуациях дубликаты могут находится в разных таблицах

6. Кандидаты, найденные тем же алгоритмом, должны быть показаны пользователю в момент заполнения новой записи. Применение этой функции в интерфейсе должно быть обязательным, а не факультативным.
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35238568
drev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
gp drev

6. Кандидаты, найденные тем же алгоритмом, должны быть показаны пользователю в момент заполнения новой записи. Применение этой функции в интерфейсе должно быть обязательным, а не факультативным.

1. это не всегда возможно, например, в случае независимого ввода и слияния
2. это не всегда удобно, например, в случае большого количества возможных дубликатов
3. это не всегда осмысленно, например, в случае ввода данных человеком, который не сможет распознать дубликат
...
Рейтинг: 0 / 0
Поиск дубликатов по схожести
    #35238796
ModelR
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
drev
1. это не всегда возможно, например, в случае независимого ввода и слияния
2. это не всегда удобно, например, в случае большого количества возможных дубликатов
3. это не всегда осмысленно, например, в случае ввода данных человеком, который не сможет распознать дубликат
Ну да, и вообще степень запущенности может быть такой, что проще создать заново чем править:)
...
Рейтинг: 0 / 0
15 сообщений из 15, страница 1 из 1
Форумы / Проектирование БД [игнор отключен] [закрыт для гостей] / Поиск дубликатов по схожести
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]