SQLinfo.ru - Все о MySQL Webew.ru: теория и практика веб-технологий

Форум пользователей MySQL

Задавайте вопросы, мы ответим

Вы не зашли.

#1 15.04.2013 13:58:11

rhiozan
Участник
Зарегистрирован: 15.04.2013
Сообщений: 5

Регексы выборки буквенно-числовых значений со специальными символами

Здравствуйте. Я тяну небольшой проект на горбу. Есть база данных, в которуб вносятся буквенно-численные коды запчастей. Сами коды имеют бувенно-численную часть и опционально один или несколько специальных символов, например:

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)".
Буду раз любой подсказке и ссылке на любой хороший учебник по регексам.

Неактивен

 

#2 15.04.2013 18:51:09

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Регексы выборки буквенно-числовых значений со специальными символами

Прежде чем разбирать данный случай, хочу уточнить: действительно ли требуется проверка рег. выражениями как таковая? Недостаточно ли условия LIKE?
Другими словами, может ли встретиться в колонке с кодами что-то, что по формату не является кодом?

Буду раз любой подсказке и ссылке на любой хороший учебник по регексам.

Механизм рег. выражений, который используется в MySQL, широтой функционала не отличается, так что там учебников особо и не нужно. Для свободного владения достаточно изучить соответствующую страницу руководства MySQL.

Что касается Perl-совместимых (PCRE — "настоящих") регулярных выражений, то можно почитать хорошо написанный раздел руководства по PHP.

P.S. А что значит "тяну проект на горбу"? smilesmile (просто интересно)

Неактивен

 

#3 15.04.2013 19:41:28

rhiozan
Участник
Зарегистрирован: 15.04.2013
Сообщений: 5

Re: Регексы выборки буквенно-числовых значений со специальными символами

Спасибо большое за внимание к моему случаю.

В искомых колонках нет ничего кроме этих кодов. К сожалению, их формат не очень чёткий, как я писал в предыдущем посте.

Касательно просто "LIKE", у меня есть записи "S(LJ)9", "09S(LJ)3$".

col0 LIKE 'SLJ' or ... - ничего не возвращает.
col0 LIKE CONCAT('__', 'SLJ', '__') ... - тоже.

Ничего не возвращает если искать по "S(LJ)".

Спасибо за ссылку на офсайт MySQL, Однако это было первым местом, куда я обратился (причём именно к англоязычной документации). К сожалению, стиль изложения там несколько непонятен мне. Впрочем, это проблема не авторов, а моя.

Ещё спасибо за ссылку на PHP-шный ресурс. Мой проект на пхп и я постоянно обращаюсь к этому справочнику, однако, регексы там меня пока минули.

Касательно "на горбу". Я не работаю в айти (хоть и учился на системного программиста), но вот, решил кое-что полезное сделать и облегчить многим работу. Личная инициатива, так сказать. А "горб" потому, что мозги ещё не думают алгоритмически так, как надо.

Неактивен

 

#4 15.04.2013 22:09:31

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Регексы выборки буквенно-числовых значений со специальными символами

Так.. Раз кроме кодов ничего нет, то, пожалуй, проверка рег. выражением не нужна. Посмотрим, что с LIKE.

В LIKE у вас по каждую сторону по два подчеркивания вместо одного. LIKE интерпретирует каждое подчеркивание как ровно один любой символ, поэтому ваше выражение  означает "найти все строки, в которых перед и после SLJ обязательно присутствуют два любых символа".

Используйте CONCAT('%', '...', '%') (как у вас написано в головном сообщении), а REGEXP уберите — получится как раз то, что вам надо.

Спасибо за ссылку на офсайт MySQL, Однако это было первым местом, куда я обратился (причём именно к англоязычной документации). К сожалению, стиль изложения там несколько непонятен мне.

Ну, тогда спрашивайте здесь smile

Если будут проблемы с регулярными выражениями в PHP (да и с PHP как таковым вообще), спрашивайте на нашем другом ресурсе — http://webew.ru/php/

Неактивен

 

#5 15.04.2013 22:45:03

rhiozan
Участник
Зарегистрирован: 15.04.2013
Сообщений: 5

Re: Регексы выборки буквенно-числовых значений со специальными символами

LazY, благодарю ещё раз за ответ.

CONCAT('%', '...', '%') - пробовал почти в самом начале. Проблема заключается в том, что коды бывают сильно похожи. К сожалению, такой запрос возвращает слишком много лишнего.

Неактивен

 

#6 16.04.2013 00:22:39

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Регексы выборки буквенно-числовых значений со специальными символами

Тогда нужно ужесточить критерий поиска. Хотя я не понимаю, как это можно сделать, исходя из вашей постановки задачи. Вам ведь нужно найти код по его фрагменту. Непонятно, как среди найденного множества выделить "годные" коды.

Неактивен

 

#7 16.04.2013 13:30:25

rhiozan
Участник
Зарегистрирован: 15.04.2013
Сообщений: 5

Re: Регексы выборки буквенно-числовых значений со специальными символами

Во, первых мне ткнули носом, что у меня в регексе нет верхнего регистра, а должно быть '^[a-zA-Z0-9\@\#\$\&\<>()]*'. Ещё я нашёл замечательную книгу: Джеффри Фридл "Регулярные выражения" 3-е издание. Книгу можно найти в сети относительно просто.

Касательно Вашего замечания. Дйствительно, задача непростая. Точно нет регулярного выражения, способного найти "09S(LJ)3$", введя "SLJ"? По  "S(LJ)9" уже находит smile
Я подумаю как разбить коды на "атомы". Возможно, именно тут кроется дьявол smile

Неактивен

 

#8 16.04.2013 23:27:29

LazY
_cмельчак
MySQL Authorized Developer and DBA
Зарегистрирован: 02.04.2007
Сообщений: 849

Re: Регексы выборки буквенно-числовых значений со специальными символами

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.." и т.п.?
Если да, то есть ли еще какие-нибудь символы, кроме скобок, которые должны подобным же образом игнорироваться?

Неактивен

 

#9 18.04.2013 18:48:54

rhiozan
Участник
Зарегистрирован: 15.04.2013
Сообщений: 5

Re: Регексы выборки буквенно-числовых значений со специальными символами

LazY, благодарю за внимание к моей проблеме. Мне удалось ей решить. Просто пришлось между каждым алфавитным символом вставлять регекс, игнорирующий специальные или цифры. В итоге имеем:


^[0-9@#$&<>()]*S[0-9@#$&<>()]*L[0-9@#$&<>()]*J[0-9@#$&<>()]*$


Таким образом, вібираются коды, текстовая часть которых совпадает с введённой пользователем, игнорируются специальные символы и цифры внутри кода, не допускаются другие алфавитные знаки вначале и конце кода. Явно неэффективно с точки зрения производительности но, как раз то, что мне нужно.

Проблема весьма специфическая. Однако, возможно, она ещё кого-нибудь приблизит к пониманию регексов.

Отредактированно rhiozan (18.04.2013 18:54:06)

Неактивен

 

Board footer

Работает на PunBB
© Copyright 2002–2008 Rickard Andersson