Найти правильное регулярное выражение - PullRequest
0 голосов
/ 30 января 2019

У меня есть такие категории: Основные категории (кошка):

  • 1
  • 2
  • ..
  • 15

Пример Sub Cat:

Для Main Cat 1:

  • 1.1.2
  • 1.1.3
  • 1.2
  • 1.11.2

Для Main Cat 2:

  • 2.1.2
  • 2.1.2.4
  • 2.12.4

Для Main Cat 15:

  • 15.11.12

Я хотел бы найти регулярное выражение для MYSQLкоторые находят категории, начинающиеся с категории .

Например (с примером выше):


Поиск категорий, начинающихся с 1 должен возвращаться:

1.1.2 1.1.3 1.2 1.11.2

Если я сделаю свое регулярное выражение, у меня будет это:

1.1.2 1.1.3 1.2 1.11.2 15.11.12 (Iне хочу этого)

Поиск категорий начинается с 1.1 должен возвращаться:

1.1.2 1.1.3

Если я сделаю свое регулярное выражение, у меня будет это:

1.1.2 1.1.3 1.11.2 (я не хочу этого)

Найти категории, начинающиеся с 2.1 , должны возвращаться:

2.1.2 2.1.2.4

Если я сделаю свое регулярное выражение, у меня будет это:

2.1.2 2.1.2.4 2.12.4 (я не хочу этого)

Спасибо за вашу помощь:)

Ответы [ 3 ]

0 голосов
/ 30 января 2019

Для MySQL до 8.0.4 Вы можете использовать маркер конца слова ([[:>:]]) в регулярном выражении, чтобы избежать выбора подкатегорий, начинающихся, например, с 2.12 при поискедля 2.1.Попробуйте что-то вроде этого:

SELECT *
FROM yourtable
WHERE category RLIKE '^2.1[[:>:]]'

Для MySQL 8.0.4 и новее он поддерживает \b в качестве границы слова, и вы можете использовать это вместо этого (обратите внимание на необходимость дублировать \ как MySQLинтерпретирует его как escape-символ внутри строк):

SELECT *
FROM yourtable
WHERE category RLIKE '^2.1\\b'
0 голосов
/ 01 февраля 2019

Для основной категории 1: LIKE '1.%'
Для основной категории 15: LIKE '15.%'
Для категории 2.1: LIKE '2.1.%'

Кроме того, с помощью LIKE вы можете использоватьINDEX(cat) для улучшения производительности.

Но ... Этого может быть недостаточно.(И я утверждаю, что Вопрос здесь был неоднозначным.) Если может быть запись только с '2.1' (без суб-подкатегории), то эти LIKE неадекватны.Итак ...

План A: col REGEXP '^2[.]1([.]|$)' - Но REGEXP не будет использовать индекс.

План B: col = '2.1' OR col LIKE '2.1.%' -- But ИЛИ не позволяет использовать индекс.

План C: неуклюжий, но самый быстрый для больших наборов данных (из-за индекса):

    WHERE col LIKE '2.1%'             -- uses INDEX(col) for quick filtering
      AND col REGEXP '^2[.]1([.]|$)'  -- avoids "2.15" and other things

Почему скобки вокруг .?:

  • . сам по себе соответствует любому одному символу - не хочу, чтобы
  • [.] соответствовал любому из набора символов, включая только период
  • \. соответствует периоду, но, в зависимости отв зависимости от контекста вам может потребоваться 1, 2 или 4 обратной косой черты.

Итог: для простоты используйте план B. Для производительности используйте план C.

0 голосов
/ 30 января 2019

Я не думаю, что вам вообще нужно регулярное выражение, и оно может быть слишком сложным.

Если вы знаете, какую категорию вы хотите найти, предполагая, что пользователь запрашивает раздел «1.1» илираздел "1.2" или "1.4.1", то вы можете искать, используя подстановочный знак.

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

Итак, если категория была 1.1, а вы хотели 1.1.0, 1.1.1, 1.1.12 и т. Д., Вы просто искали бы все, что соответствует 1.1.%, Что означает поиск всего, что 1.1, за которым следуетточка, за которой не следует число.

Пример запроса:

$category = "1.1";
$sql = "SELECT * FROM [your_table] WHERE cat LIKE '".$category.".%'";

Этот запрос будет соответствовать:

1.1.0
1.1.1
1.1.15
// Any anything else starting with 1.1.
...