2016-04-20 2 views
1

Я пытаюсь выяснить, есть ли у кого-то элегантный способ поиска шаблонов в данных, хранящихся в поле varchar, где значение неизвестно, а это значит, что я не могу использовать LIKE. Например, скажем, таблица называется тест выглядит следующим образом:MySQL - поиск шаблонов

id, str 

и данные выглядели так:

1, YUUUY 
2, DDDMM 
3, MMMMT 
4, XMXMX 

, и я хочу, чтобы сделать выбор, который будет возвращать что-либо, где значение ул имеет шаблон, соответствующий шаблону ABABA. ABABA здесь показывает шаблон, а не буквальные буквы. Таким образом, единственное, что соответствует этому шаблону, будет id = 4. Существует ли регулярное выражение, которое я могу использовать для сопоставления шаблонов так? Для того, чтобы убедиться, что я ясно относительно моделей:

The pattern for id=1 is ABBBA. 
The pattern for id=2 is AAABB. 
The pattern for id=3 is AAAAB. 

При выполнении запроса, все, что я знаю, это образец для поиска.

С другой стороны, если это делает его легче, я могу быть таблица создана как:

id,c1,c2,c3,c4,c5 

и данные будут выглядеть следующим образом:

1,Y,U,U,U,Y 
2,D,D,D,M,M 
3,M,M,M,M,T 
4,X,M,X,M,X 

Не уверен, что делает его более легким , но я думаю, что regexp выходит из окна, если данные настроены так.

+0

Некоторые вещи не должны выполняться в SQL. –

ответ

0

К сожалению, это не похоже, что MySQL поддерживает группы регулярных выражений. Я надеялся, что вы могли бы сделать что-то вроде этого, чтобы соответствовать ABBBA, например:

([A-Z])([A-Z])\2\2\1 

Пример здесь: http://regexr.com/3d8gu

Похоже, есть плагин MySQL, который мог бы поддержать его:

https://github.com/mysqludf/lib_mysqludf_preg

Вот настоящий хакерский способ сделать это.

ABBBA (или YUUUY и т.д.):

SELECT id, name FROM table WHERE  
    substring(name,1,1) = substring(name,5,1) AND  
    substring(name,2,1) = substring(name,3,1) AND 
    substring(name,3,1) = substring(name,4,1); 

AAABB (или DDDMM и т.д.):

SELECT id, name FROM table WHERE  
    substring(name,1,1) = substring(name,2,1) AND  
    substring(name,2,1) = substring(name,3,1) AND 
    substring(name,4,1) = substring(name,5,1); 

AAAAB (или MMMMT и т.д.):

SELECT id, name FROM table WHERE  
    substring(name,1,1) = substring(name,2,1) AND  
    substring(name,2,1) = substring(name,3,1) AND 
    substring(name,3,1) = substring(name,4,1) AND 
    substring(name,4,1) != substring(name,5,1); 

You получить изображение ...

Было бы похоже i f вы разделили данные на разные столбцы. Вместо сравнения подстрок вы просто сравниваете столбцы.

+0

Спасибо за информацию. Что-то вроде примера групп регулярных выражений - это то, что я искал, но я не готов установить плагин на этом этапе. У меня есть несколько хакерских способов сделать это, и похоже, что мне нужно это сделать. Я должен был также указать, что столбец может не содержать 5 символов. Это может быть от одного до восьми, и я не решил, разрешить ли C в шаблоне ex. ABCBA. Это делает хакерское решение намного сложнее. Я, вероятно, позабочусь об этом в PHP, а не в MySQL. Еще раз спасибо за ответ. – Travis

0

Нет поддержки регулярных выражений в MySQL, чтобы сделать подобный тип соответствия, нет.

SQL не был специально разработан для сопоставления с шаблоном строк (или шаблонов значений в отдельных столбцах.)

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

Предположим, что мы не имеем встроенный пользовательский определенную пользователем функцию, и мы хотим использовать родной MySQL функции и выражение ...

И если предположить, что модели мы ищем гарантированно состоять только из два различных персонажей ...

и предполагая, что мы ищем ровно пять позиций символов ...

И если предположить, что образец строки мы соответствие всегда будет начинаться с буквы «A ', а «другая» буква в шаблоне также будет «B»

Это не будет слишком уродливым, чтобы сделать что-то вроде этого:

SELECT t.id 
    , t.str 
    FROM myable t   
WHERE CONCAT('A' 
     ,IF(MID(t.str,2,1)=MID(t.str,1,1),'A','B') 
     ,IF(MID(t.str,3,1)=MID(t.str,1,1),'A','B') 
     ,IF(MID(t.str,4,1)=MID(t.str,1,1),'A','B') 
     ,IF(MID(t.str,5,1)=MID(t.str,1,1),'A','B') 
    ) = 'ABBBA' 

Первый символ в строке автоматически преобразуется в «A».

Второй символ, если он соответствует первому символу, тогда это также «A», иначе это «B».

Мы делаем то же самое для третьего, четвертого и пятого символов.

Объединить символы «A» и «B» в одну строку, и теперь мы можем выполнить сравнение равенства с строкой шаблона, состоящей из «A» и «B», начиная с «A».

Но это будет разваливаться, если указанные предположения неверны. Если str имеет длину не более пяти символов, если она содержит более двух различных символов (мы увидим, что первый символ соответствует ... это будет видеть str = XYYZX в качестве совпадающего шаблона ABBBA. (Первый символ автоматически соответствует A , а пятый символ совпадает с первым, поэтому он является символом A, а все остальные символы не совпадают, поэтому они являются «B», хотя они не совпадают.

И так далее.

Мы могли бы добавить некоторые дополнительные проверки.

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

AND CHAR_LENGTH(t.str)=5 

Обратите внимание, что сортировка по умолчанию в MySQL нечувствительна к регистру. Это означает, что значение str MmmmM будет преобразовано в «AAAAA», а не «ABBBA». И значение str для MmmKk будет соответствовать «AAABB».

+0

Спасибо за информацию Спенсер. Я должен был также указать, что столбец может не содержать 5 символов. Это может быть от одного до восьми, и я не решил, разрешить ли C в шаблоне ex. ABCBA. Это делает этот тип решения более сложным. Я, вероятно, позабочусь об этом в PHP, а не в MySQL. Еще раз спасибо за ответ, и мне нравится, где вы пошли с решением. Я могу использовать что-то подобное для выполнения задачи. – Travis

+0

@Travis: Пример, который я дал, выглядит довольно простым, и я думаю, что он работает для всех примеров в вопросе.Это выглядит просто, потому что он обрабатывает только небольшой набор специальных случаев. Расширение и обобщение этого подхода было бы утомительным, выражения для этого стали бы чрезмерно сложными. – spencer7593

Смежные вопросы