Задавайте вопросы, мы ответим
Вы не зашли.
Страниц: 1
Здравствуйте. Я тяну небольшой проект на горбу. Есть база данных, в которуб вносятся буквенно-численные коды запчастей. Сами коды имеют бувенно-численную часть и опционально один или несколько специальных символов, например:
A, Bb, 2C8, A7(BO)19, B29H$, 29H(6JI)0#, 29H(6JI)0#^
Пользователь ищет записи, вводя один или несколько кодов. Любой код может встретиться в одной из нескольких колонок кортежа. Поэтому каждый код нужно искать во всех колонках. Нормализация базы не выход, поскольку кодов очень много, их порядок размещения имеет значение, а записей в бд не так уж и много (менее 30 тысяч).
Запрос имеет вид:
SELECT * FROM table WHERE ID IN(SELECT ID FROM table WHERE (((col0 REGEXP '^[a-z0-9\@\#\$\^\&()]*$' AND col0 LIKE CONCAT('%', '$v', '%'))OR ... OR(col4 REGEXP '^[a-z0-9\@\#\$\^\&()]*$' AND col4 LIKE CONCAT('%', '$v', '%')))AND ... AND((col0 REGEXP '^[a-z0-9\@\#\$\^\&()]*$' AND col0 LIKE CONCAT('%', '$v5', '%'))OR ... OR(col4 REGEXP '^[a-z0-9\@\#\$\^\&()]*$' AND col4 LIKE CONCAT('%', '$v5', '%')))) and othercol is NOT null)
Проблема в том, что запрос не возвращает коды записей "S(LJ)9", "09S(LJ)3$", если я ищу "SLJ" или "S(LJ)".
Буду раз любой подсказке и ссылке на любой хороший учебник по регексам.
Неактивен
Прежде чем разбирать данный случай, хочу уточнить: действительно ли требуется проверка рег. выражениями как таковая? Недостаточно ли условия LIKE?
Другими словами, может ли встретиться в колонке с кодами что-то, что по формату не является кодом?
Буду раз любой подсказке и ссылке на любой хороший учебник по регексам.
Механизм рег. выражений, который используется в MySQL, широтой функционала не отличается, так что там учебников особо и не нужно. Для свободного владения достаточно изучить соответствующую страницу руководства MySQL.
Что касается Perl-совместимых (PCRE — "настоящих") регулярных выражений, то можно почитать хорошо написанный раздел руководства по PHP.
P.S. А что значит "тяну проект на горбу"? (просто интересно)
Неактивен
Спасибо большое за внимание к моему случаю.
В искомых колонках нет ничего кроме этих кодов. К сожалению, их формат не очень чёткий, как я писал в предыдущем посте.
Касательно просто "LIKE", у меня есть записи "S(LJ)9", "09S(LJ)3$".
col0 LIKE 'SLJ' or ... - ничего не возвращает.
col0 LIKE CONCAT('__', 'SLJ', '__') ... - тоже.
Ничего не возвращает если искать по "S(LJ)".
Спасибо за ссылку на офсайт MySQL, Однако это было первым местом, куда я обратился (причём именно к англоязычной документации). К сожалению, стиль изложения там несколько непонятен мне. Впрочем, это проблема не авторов, а моя.
Ещё спасибо за ссылку на PHP-шный ресурс. Мой проект на пхп и я постоянно обращаюсь к этому справочнику, однако, регексы там меня пока минули.
Касательно "на горбу". Я не работаю в айти (хоть и учился на системного программиста), но вот, решил кое-что полезное сделать и облегчить многим работу. Личная инициатива, так сказать. А "горб" потому, что мозги ещё не думают алгоритмически так, как надо.
Неактивен
Так.. Раз кроме кодов ничего нет, то, пожалуй, проверка рег. выражением не нужна. Посмотрим, что с LIKE.
В LIKE у вас по каждую сторону по два подчеркивания вместо одного. LIKE интерпретирует каждое подчеркивание как ровно один любой символ, поэтому ваше выражение означает "найти все строки, в которых перед и после SLJ обязательно присутствуют два любых символа".
Используйте CONCAT('%', '...', '%') (как у вас написано в головном сообщении), а REGEXP уберите — получится как раз то, что вам надо.
Спасибо за ссылку на офсайт MySQL, Однако это было первым местом, куда я обратился (причём именно к англоязычной документации). К сожалению, стиль изложения там несколько непонятен мне.
Ну, тогда спрашивайте здесь
Если будут проблемы с регулярными выражениями в PHP (да и с PHP как таковым вообще), спрашивайте на нашем другом ресурсе — http://webew.ru/php/
Неактивен
LazY, благодарю ещё раз за ответ.
CONCAT('%', '...', '%') - пробовал почти в самом начале. Проблема заключается в том, что коды бывают сильно похожи. К сожалению, такой запрос возвращает слишком много лишнего.
Неактивен
Тогда нужно ужесточить критерий поиска. Хотя я не понимаю, как это можно сделать, исходя из вашей постановки задачи. Вам ведь нужно найти код по его фрагменту. Непонятно, как среди найденного множества выделить "годные" коды.
Неактивен
Во, первых мне ткнули носом, что у меня в регексе нет верхнего регистра, а должно быть '^[a-zA-Z0-9\@\#\$\&\<>()]*'. Ещё я нашёл замечательную книгу: Джеффри Фридл "Регулярные выражения" 3-е издание. Книгу можно найти в сети относительно просто.
Касательно Вашего замечания. Дйствительно, задача непростая. Точно нет регулярного выражения, способного найти "09S(LJ)3$", введя "SLJ"? По "S(LJ)9" уже находит
Я подумаю как разбить коды на "атомы". Возможно, именно тут кроется дьявол
Неактивен
rhiozan написал:
мне ткнули носом, что у меня в регексе
нет верхнего регистра
Ткните их носом в ответ:
http://dev.mysql.com/doc/refman/5.6/en/regexp.html написал:
REGEXP is not case sensitive, except when used with binary strings.
mysql> SELECT 'A' REGEXP 'a'; +----------------+ | 'A' REGEXP 'a' | +----------------+ | 1 | +----------------+ 1 row in set (0.00 sec)
rhiozan написал:
нашёл замечательную книгу: Джеффри Фридл "Регулярные выражения" 3-е издание.
Да, книга исчерпывающая. После её прочтения и никакие руководства не нужны (правда, учтите, что там придется читать порядка 400 страниц).
rhiozan написал:
Точно нет регулярного выражения, способного найти "09S(LJ)3$", введя "SLJ"?
Так, вот здесь давайте уточним: поиск не учитывает скобки? Т.е. в ответ на "SLJ" должно искать "..SLJ..", "..S(L)J..", "..(SL)J.." и т.п.?
Если да, то есть ли еще какие-нибудь символы, кроме скобок, которые должны подобным же образом игнорироваться?
Неактивен
LazY, благодарю за внимание к моей проблеме. Мне удалось ей решить. Просто пришлось между каждым алфавитным символом вставлять регекс, игнорирующий специальные или цифры. В итоге имеем:
Отредактированно rhiozan (18.04.2013 18:54:06)
Неактивен
Страниц: 1