Алгоритм поискаслов в строке
#1
Отправлено 22.09.2004, 14:45:15
к примеру имеем поле в базе данных с названием организации
допустим "ТОО Светлый путь"
кто-то взял да написал не "Светлый" а "Свелтый", просто ошибся при вводе, или пропустил одну буковку "Свелый"
а вот юзер в поиске делает запрос как надо, то есть ищет по слову "Светлый"
как найти слова как нормальные так и с ошибками?
где-то видел такой поиск, кажется на http://www.amadeus.net, при поиске названия аэропортов.
есть вариант такой, сплитим буковки и начинаем перебор строки, где есть все такие буквы, то есть найдем все названия, где могли перепутать положение букв как в примере "Свелтый".
далее делаем почти тоже самое, только убираем одну из буковок, и так несколько раз, в зависимости от количества буков в слове по каждой букве.
тока млин это жутко долго!!! и требует ресурсов
может есть другие варианты? не пинайте меня, я самоучка и в политехе не учился
#2
Отправлено 23.09.2004, 14:03:11
Время обработки ->ooнужно создать поиск слова по полю
к примеру имеем поле в базе данных с названием организации
допустим "ТОО Светлый путь"
кто-то взял да написал не "Светлый" а "Свелтый", просто ошибся при вводе, или пропустил одну буковку "Свелый"
а вот юзер в поиске делает запрос как надо, то есть ищет по слову "Светлый"
как найти слова как нормальные так и с ошибками?
есть вариант такой, сплитим буковки и начинаем перебор строки, где есть все такие буквы, то есть найдем все названия, где могли перепутать положение букв как в примере "Свелтый".
Время обработки ->ooдалее делаем почти тоже самое, только убираем одну из буковок, и так несколько раз, в зависимости от количества буков в слове по каждой букве.
И в обоих случаях вываливается куча совпадений, которые совпадениями не являются.
Точно.тока млин это жутко долго!!! и требует ресурсов
может есть другие варианты? не пинайте меня, я самоучка и в политехе не учился
В MSSQL есть оператор DIFFERENCE, который определяет уровень созвучности слов на основе SOUNDEX.
Приемлемо работает, к сожалению, только с ангийским.
Народ писал подобное для русских слов, но варианты тоже были не самыми лучшими. Поищи на http://www.sql.ru/
Вообще, такие вещи лучше отлавливать на этапе занесения инфы в базу. Например юзать вордовский спелчеккер. Тоже не всегда прокатывает (особенно для имен собственных), но помогает.
Еще помогает двойная вычитка. Т.е. вычитывает тот, кто заносит, после него вычитывает проверяльщик.
Разбирать такие проколы на этапе поиска занятие малоэффективное. Эти проколы нужно фильтровать еще на входе.
Сообщение отредактировал Shirson: 23.09.2004, 14:06:06
#3
Отправлено 23.09.2004, 21:34:45
Если программа ищет в поле БД точное соответствие пользовательскому вводу, то она по-любому его не найдет, хоть вводи в поле поиска "Свелтый", хоть "Светлый": в БД, согласно условию, хранится название "ТОО Свелтый путь".нужно создать поиск слова по полю
к примеру имеем поле в базе данных с названием организации
допустим "ТОО Светлый путь"
кто-то взял да написал не "Светлый" а "Свелтый", просто ошибся при вводе, или пропустил одну буковку "Свелый"
а вот юзер в поиске делает запрос как надо, то есть ищет по слову "Светлый"
К счастью, в языке запросов SQL существует прекрасная конструкция LIKE, которая определяет, начинается ли строковое значение с одного или нескольких символов. Чтобы оператор с использованием LIKE правильно работал, туда следует добавить шаблон в виде символа "*" или одного или нескольких символов "?".
Например:
LIKE "TOO*" (возвратит значение "True" для кучи названий организаций, начинающихся с "ТОО")
LIKE "ТОО Све*" (возвратит "True" для "ТОО Свелтый путь", и возможно, еще для нескольких).
LIKE "??? Све*" (возвратит "True" не только для всех "ТОО Све...", но еще и для всяких разных ЗАО, ОАО, ООО, КСК и даже МЧП , начинающихся со "Све").
Если вы используете язык VBA, например, из MS Access 2000, то выражение LIKE "TOO*" будет эквивалентно функции Access VBA InStr(Left (FieldName,3), "TOO").
Вообще, лучше делать так, чтобы юзер видел названия (организаций, городов, областей и т.д.), а программа работала только с уникальными числовыми идентификаторами, которые с этими названиями однозначно связаны. К примеру, переименовали Акмолу в Астану - ничего страшного, переименуем ее и в БД для соответствующего числового идентификатора, при этом в БД никакой новый город, конечно, не появится.
Сообщение отредактировал Visual1: 23.09.2004, 21:53:51
#6
Отправлено 24.09.2004, 13:04:50
1. Можно использовать метод, предложенный Visual1. С таким же успехом применимы регулярные выражения. По сути это одно и тоже...
Не знаю в какой среде ты пишешь, библиотека TRegExpr для Дельфи лежит здесь...
Краткое описание с примером - тут...
2. Функция приблизительного/нечеткого сравнения строк - реализована на Дельфи, лежит тут - с исходниками и примерами...
Наверное, самый подходящий способ в данном случае...
3. Нейронная сеть Хэмминга (ассоциативная память)...
Сложный (на стадии изучения ), но действенный метод ...
- Мат. аппарат;
- пример;
- откомпилированный пример, без исходников.
Надеюсь, чем-нибудь помог... Удачи!
З.Ы. Еще несколько статей по нечеткому поиску:
1 и 2.
Сообщение отредактировал Whistle: 24.09.2004, 13:07:42
#7
Отправлено 24.09.2004, 15:45:05
Это, простите, в каком SQL такое?К счастью, в языке запросов SQL существует прекрасная конструкция LIKE, которая определяет, начинается ли строковое значение с одного или нескольких символов. Чтобы оператор с использованием LIKE правильно работал, туда следует добавить шаблон в виде символа "*" или одного или нескольких символов "?".
По стандату SQL любой символ идёт как "_" (подчёркивание), а любой набор символов - "%"
Не пробовали прикинуть трудозатраты на подобный поиск? Когда на пользователя вываливается тысяча записей, из которых ему нужна одна или две.LIKE "TOO*" (возвратит значение "True" для кучи названий организаций, начинающихся с "ТОО")
LIKE "ТОО Све*" (возвратит "True" для "ТОО Свелтый путь", и возможно, еще для нескольких).
LIKE "??? Све*" (возвратит "True" не только для всех "ТОО Све...", но еще и для всяких разных ЗАО, ОАО, ООО, КСК и даже МЧП , начинающихся со "Све").
Для ограниченного числа вариантов значений это отличный вариант.Вообще, лучше делать так, чтобы юзер видел названия (организаций, городов, областей и т.д.), а программа работала только с уникальными числовыми идентификаторами, которые с этими названиями однозначно связаны. К примеру, переименовали Акмолу в Астану - ничего страшного, переименуем ее и в БД для соответствующего числового идентификатора, при этом в БД никакой новый город, конечно, не появится.
Еще прикрутить эвент, который будет реагировать на ввод не существующего до сего момента значения и спрашивать у юзера, новые это данные или опечатка.
#9
Отправлено 24.09.2004, 18:08:22
Символы подстановки, указанные Вами ("%" и "_"), действительно, используются в ANSI SQL. Однако в Jet SQL из настольной СУБД MS Access, на примере которой я и давал свой ответ, для описания произвольного количества символов и одного символа применяются символы "*" и "?" соответственно.Это, простите, в каком SQL такое?К счастью, в языке запросов SQL существует прекрасная конструкция LIKE, которая определяет, начинается ли строковое значение с одного или нескольких символов. Чтобы оператор с использованием LIKE правильно работал, туда следует добавить шаблон в виде символа "*" или одного или нескольких символов "?".
По стандату SQL любой символ идёт как "_" (подчёркивание), а любой набор символов - "%"
Эту ситуацию может и должен предусмотреть программист. Например, можно потребовать от юзера, чтобы предварительно ввел (выбрал из раскрывающегося списка) название области, или еще какие-нибудь уточняющие сведения (например, данные только за этот год), и только затем ему будут показаны все организации, начинающиеся на "Све..." из данной области. Надеюсь, не требуется доказывать, что даже в Алматинской области таковых на тысячу не наберется. Ну и юзер, конечно, тоже не должен быть совсем уж чайником (надо ему в хелпе указать мягко, но твердо , чтобы не вводил слишком уж широкие запросы, эквивалентные одной лишь "*").Не пробовали прикинуть трудозатраты на подобный поиск? Когда на пользователя вываливается тысяча записей, из которых ему нужна одна или две.LIKE "TOO*" (возвратит значение "True" для кучи названий организаций, начинающихся с "ТОО")
LIKE "ТОО Све*" (возвратит "True" для "ТОО Свелтый путь", и возможно, еще для нескольких).
LIKE "??? Све*" (возвратит "True" не только для всех "ТОО Све...", но еще и для всяких разных ЗАО, ОАО, ООО, КСК и даже МЧП , начинающихся со "Све").
Я именно и предполагал, что автор вопроса работает с какой-нибудь настольной СУБД и ограниченным числом записей, а не с мощными клиент-серверными базами (иначе он вообще вряд ли задавал бы подобные вопросы). Эвент можно прикрутить, это точно, а еще можно установить права пользователей, а еще можно не давать пользователям вводить названия организаций, а позволять им только чтобы выбирали готовые названия из раскрывающегося списка, формировать который может только админ в головном офисе... Нет предела совершенству.Для ограниченного числа вариантов значений это отличный вариант.Вообще, лучше делать так, чтобы юзер видел названия (организаций, городов, областей и т.д.), а программа работала только с уникальными числовыми идентификаторами, которые с этими названиями однозначно связаны. К примеру, переименовали Акмолу в Астану - ничего страшного, переименуем ее и в БД для соответствующего числового идентификатора, при этом в БД никакой новый город, конечно, не появится.
Еще прикрутить эвент, который будет реагировать на ввод не существующего до сего момента значения и спрашивать у юзера, новые это данные или опечатка.
#11
Отправлено 24.09.2004, 18:54:46
Честно говоря, не знал, что Jet SQL не отвечает стандарту SQL-92.Символы подстановки, указанные Вами ("%" и "_"), действительно, используются в ANSI SQL. Однако в Jet SQL из настольной СУБД MS Access, на примере которой я и давал свой ответ, для описания произвольного количества символов и одного символа применяются символы "*" и "?" соответственно.
Учту.
Таки да. Я просто привык работать с ...э... несколько большими БДЭту ситуацию может и должен предусмотреть программист. Например, можно потребовать от юзера, чтобы предварительно ввел (выбрал из раскрывающегося списка) название области, или еще какие-нибудь уточняющие сведения (например, данные только за этот год), и только затем ему будут показаны все организации, начинающиеся на "Све..." из данной области. Надеюсь, не требуется доказывать, что даже в Алматинской области таковых на тысячу не наберется.
Для конкретной задачи выбор из списка идёт.
(мечтает о маленькой БД на 50000 записей...)Я именно и предполагал, что автор вопроса работает с какой-нибудь настольной СУБД и ограниченным числом записей, а не с мощными клиент-серверными базами (иначе он вообще вряд ли задавал бы подобные вопросы).
Можно поудобнее сделать.Эвент можно прикрутить, это точно, а еще можно установить права пользователей, а еще можно не давать пользователям вводить названия организаций, а позволять им только чтобы выбирали готовые названия из раскрывающегося списка, формировать который может только админ в головном офисе... Нет предела совершенству.
В таблице, где выводится список, поставить FastFind. Пользователь набирает имя, таблица автоматом прокручивается по введённым частям слова (как Lingvo или в этом же роде).
Вообще да, для небольших решений можно придумать много всяких красивостей)
#12
Отправлено 25.09.2004, 02:26:51
Что ж, таково Ваше (с недавних пор) мнение. Но не спешите - есть еще мнение Роджера Дженнингса (Roger Jennings), весьма авторитетного специалиста по Access, SQL Server и другим продуктам Microsoft. Открываем его книгу "Использование Microsoft Access 2000. Специальное издание", и на стр. 849 читаем:Честно говоря, не знал, что Jet SQL не отвечает стандарту SQL-92.
Учту.
"Access поддерживает не все ключевые слова ANSI SQL, но каждая модификация Jet отвечает стандарту SQL-92."
#14
Отправлено 27.09.2004, 17:38:59
или то же самое
http://www.delphikin...ury/compare.htm
там примерчик на дельфи.
Я в свое время что то подобное пытался сделать (проверка фамилий), даже пытался на plsql переписать, но в виду огромной обрабатываемой базы - проще было сделать грамотный ввод данных и долбить пользователей на уровне распоряжений.
#15
Отправлено 27.09.2004, 18:36:07
Честно говоря, и я тоже. Просто процитировал дословно, как сказано в книге. Там вообще-то есть e-mail автора, но беспокоить его по такому поводу мне бы не хотелось. Уж очень он уважаемый человек - автор свыше 20 книг, один из ведущих бета-тестеров Access и SQL Server, редактор программерского журнала, один из составителей электронной справочной системы MSDN Library, президент консалтинговой компании в Калифорнии, и т.д.Бррр....
Что-то я не втыкаюсь.
По стандарту wildchars идут как _ и %, а не ? и *
#16
Отправлено 28.09.2004, 08:17:07
И Roger Jennings либо ламо последнее, либо (более вероятно) переводили наши гениЯльные переводчики
А теперь - ВНИМАНИЕ! Ни одна версия MS Access никогда небыла ANSI SQL XX level 1 compliant! ANSI SQL - это видишь ли четкий стандарт, и нельзя быть слегка беремменной
Чтобы не обвинили в голословности вот вам цитата от самих MS:
"This mode conforms closely to the ANSI-92 Level 1 specification but is not ANSI-92 Level 1 compliant. This query mode has more of the ANSI syntax, and the wildcard characters conform to the SQL specification."
Это про MS Access 2002 ANSI-92 query mode. Там вилдкарды уже по ANSI SQL. Про 2003 пока сказать не могу - оно как то само отвалилось Не юзаю я их терерь _вообще_
Всем спасибо за внимание, и с каждого по рублю за лекцию
#17
Отправлено 28.09.2004, 14:30:16
С wildcards ами запаришься, чуть база разрастется.. караул.. такие тормоза будут, индексы не помогут.
Сообщение отредактировал BIGGboss: 28.09.2004, 14:32:01
#18
Отправлено 28.09.2004, 18:37:17
#19
Отправлено 28.09.2004, 20:18:04
Если я не прав, то укажите, плз, в чем? Что, нельзя применять LIKE и символы "*" и "?" для поиска подстроки, когда работаешь в Access?Visual1, я конечно сорри - но Вы не правы!
И Roger Jennings либо ламо последнее, либо (более вероятно) переводили наши гениЯльные переводчики
Насчет того, что Roger Jennings "ламо последнее" - Вам, возможно, виднее. Правда, его нет на этом форуме, и ответить Вам он не может. А я, еще раз повторяю, лишь дословно процитировал, что было сказано в книге, а вовсе не настаивал на правильности приведенной цитаты.
Насчет наших "гениЯльных" переводчиков мне тоже мысль приходила. В данном случае эту мысль я не стал развивать - уж очень фраза простая, чтобы даже средний переводчик на ней споткнулся. В книге есть гораздо более сложные фразы, и с ними переводчики успешно справились.
Но уже в нескольких последних версиях есть средства для быстрой и легкой конвертации БД из формата MS Access в MS SQL Server, который из всех существующих наиболее близок к стандарту ANSI SQL. Так что, если кто на дух не переносит wildcards одного типа, а предпочитает другие - no problem.А теперь - ВНИМАНИЕ! Ни одна версия MS Access никогда небыла ANSI SQL XX level 1 compliant! ANSI SQL - это видишь ли четкий стандарт, и нельзя быть слегка беремменной
Лучше наоборот, с Вас - каждому.Всем спасибо за внимание, и с каждого по рублю за лекцию
#20
Отправлено 29.09.2004, 08:40:49
Вот в этом:
>"Access поддерживает не все ключевые слова ANSI SQL,
> но каждая модификация Jet отвечает стандарту SQL-92."
Кстати, если автор настолько проффесионал - почему же родную документацию не читает?-) Ссылку я приводил.
>MS SQL Server, который из всех существующих наиболее близок к стандарту ANSI SQL
Тоже перл Так что по рублику со всех, а то пивнушку закроют
Количество пользователей, читающих эту тему: 1
пользователей: 0, неизвестных прохожих: 1, скрытых пользователей: 0