Шаблон регулярных выражений не работает с регулярными выражениями MySQL - PullRequest
0 голосов
/ 16 апреля 2019

У меня есть приведенное ниже регулярное выражение, которое отлично работает с тестером Regex (благодаря horcrux ).Тем не менее, он не возвращает совпадений, когда я использую его с MySQL regexp

select query from search s where s.query regexp '^((&|^)(serviceType=SALE|propertyType=HOUSE|city=1)){1,3}$'

Выше должно соответствовать ниже

serviceType=SALE&propertyType=HOUSE&city=1
propertyType=HOUSE&serviceType=SALE&city=1
city=1&propertyType=HOUSE&serviceType=SALE
city=1&serviceType=SALE&propertyType=HOUSE
serviceType=SALE&propertyType=HOUSE
serviceType=SALE

, но не эти

serviceType=SALE&propertyType=HOUSE&city=2
propertyType=HOUSE&city=2&serviceType=SALE
city=2&propertyType=HOUSE&serviceType=SALE
serviceType=SALE&propertyType=FARM&city=1
serviceType=SALE&propertyType=UNIT
serviceType=RENTAL&propertyType=HOUSE
serviceType=RENTAL

Ответы [ 2 ]

0 голосов
/ 16 апреля 2019

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

Запрос

 SELECT 
   separated_key_values.query
 , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           separated_key_values.separated_property
         , '='
         , 1
       )
      ,'='
     , -1
   ) AS property_key
 , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           separated_key_values.separated_property
         , '='
         , 2
       )
      ,'='
     , -1
   ) AS property_value   
FROM (

SELECT 
  DISTINCT
     search.query 
   , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           search.query
         , '&'
         , number_generator.row_number
       )
      ,'&'
     , -1
   ) separated_property
FROM (
  SELECT 
   @row := @row + 1 AS row_number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row2  
  CROSS JOIN (
    SELECT @row := 0 
  ) AS init_user_params
) AS number_generator
CROSS JOIN 
 search 

) AS separated_key_values
ORDER BY 
 separated_key_values.query ASC

Результат

| query                                      | property_key | property_value |
| ------------------------------------------ | ------------ | -------------- |
| city=1&propertyType=HOUSE&serviceType=SALE | city         | 1              |
| city=1&propertyType=HOUSE&serviceType=SALE | serviceType  | SALE           |
| city=1&propertyType=HOUSE&serviceType=SALE | propertyType | HOUSE          |
| city=1&serviceType=SALE&propertyType=HOUSE | city         | 1              |
| city=1&serviceType=SALE&propertyType=HOUSE | propertyType | HOUSE          |
| city=1&serviceType=SALE&propertyType=HOUSE | serviceType  | SALE           |
| city=2&propertyType=HOUSE&serviceType=SALE | serviceType  | SALE           |
| city=2&propertyType=HOUSE&serviceType=SALE | city         | 2              |
| city=2&propertyType=HOUSE&serviceType=SALE | propertyType | HOUSE          |
| propertyType=HOUSE&city=2&serviceType=SALE | city         | 2              |
| propertyType=HOUSE&city=2&serviceType=SALE | serviceType  | SALE           |
| propertyType=HOUSE&city=2&serviceType=SALE | propertyType | HOUSE          |
| propertyType=HOUSE&serviceType=SALE&city=1 | city         | 1              |
| propertyType=HOUSE&serviceType=SALE&city=1 | serviceType  | SALE           |
| propertyType=HOUSE&serviceType=SALE&city=1 | propertyType | HOUSE          |
| serviceType=RENTAL                         | serviceType  | RENTAL         |
| serviceType=RENTAL&propertyType=HOUSE      | propertyType | HOUSE          |
| serviceType=RENTAL&propertyType=HOUSE      | serviceType  | RENTAL         |
| serviceType=SALE                           | serviceType  | SALE           |
| serviceType=SALE&propertyType=FARM&city=1  | serviceType  | SALE           |
| serviceType=SALE&propertyType=FARM&city=1  | propertyType | FARM           |
| serviceType=SALE&propertyType=FARM&city=1  | city         | 1              |
| serviceType=SALE&propertyType=HOUSE        | propertyType | HOUSE          |
| serviceType=SALE&propertyType=HOUSE        | serviceType  | SALE           |
| serviceType=SALE&propertyType=HOUSE&city=1 | city         | 1              |
| serviceType=SALE&propertyType=HOUSE&city=1 | propertyType | HOUSE          |
| serviceType=SALE&propertyType=HOUSE&city=1 | serviceType  | SALE           |
| serviceType=SALE&propertyType=HOUSE&city=2 | propertyType | HOUSE          |
| serviceType=SALE&propertyType=HOUSE&city=2 | city         | 2              |
| serviceType=SALE&propertyType=HOUSE&city=2 | serviceType  | SALE           |
| serviceType=SALE&propertyType=UNIT         | propertyType | UNIT           |
| serviceType=SALE&propertyType=UNIT         | serviceType  | SALE           |

см. демо

После этого это так же просто, как добавление в качестве условного агрегирования.

Запрос

SELECT 
  separated_key_values.query

, 

 (
   SUM(separated_key_values.property_key = 'serviceType') > 0
 AND
   SUM(separated_key_values.property_value = 'SALE') > 0

 ) AS has_serviceType_SALE

, 

 (
   SUM(separated_key_values.property_key = 'propertyType') > 0
 AND
   SUM(separated_key_values.property_value = 'HOUSE') > 0

 ) AS has_propertyType_HOUSE

, 

 (
   SUM(separated_key_values.property_key = 'City') > 0
 AND
   SUM(separated_key_values.property_value = '1') > 0

 )  AS has_City_1

, (

 (
   SUM(separated_key_values.property_key = 'serviceType') > 0
 AND
   SUM(separated_key_values.property_value = 'SALE') > 0

 ) 

 + 

 (
   SUM(separated_key_values.property_key = 'propertyType') > 0
 AND
   SUM(separated_key_values.property_value = 'HOUSE') > 0

 ) 

 + 

 (
   SUM(separated_key_values.property_key = 'City') > 0
 AND
   SUM(separated_key_values.property_value = '1') > 0

 )   

  ) AS has_mask 

, COUNT(*)

FROM (
SELECT 
   search_alias.query
 , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           search_alias.separated_property
         , '='
         , 1
       )
      ,'='
     , -1
   ) AS property_key
 , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           search_alias.separated_property
         , '='
         , 2
       )
      ,'='
     , -1
   ) AS property_value   
FROM (

SELECT 
  DISTINCT
     search.query 
   , SUBSTRING_INDEX(
       SUBSTRING_INDEX(
           search.query
         , '&'
         , number_generator.row_number
       )
      ,'&'
     , -1
   ) separated_property
FROM (
  SELECT 
   @row := @row + 1 AS row_number
  FROM (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row1
  CROSS JOIN (
    SELECT 0 UNION SELECT 1 UNION SELECT 2 UNION SELECT 3 UNION SELECT 4 UNION SELECT 5 UNION SELECT 6 UNION SELECT 7 UNION SELECT 8 UNION SELECT 9
  ) row2  
  CROSS JOIN (
    SELECT @row := 0 
  ) AS init_user_params
) AS number_generator
CROSS JOIN 
 search 

) AS search_alias
) AS separated_key_values
GROUP BY 
 separated_key_values.query
HAVING 
 has_mask = COUNT(*)

Результат

| query                                      | has_serviceType_SALE | has_propertyType_HOUSE | has_City_1 | has_mask | COUNT(*) |
| ------------------------------------------ | -------------------- | ---------------------- | ---------- | -------- | -------- |
| city=1&propertyType=HOUSE&serviceType=SALE | 1                    | 1                      | 1          | 3        | 3        |
| city=1&serviceType=SALE&propertyType=HOUSE | 1                    | 1                      | 1          | 3        | 3        |
| propertyType=HOUSE&serviceType=SALE&city=1 | 1                    | 1                      | 1          | 3        | 3        |
| serviceType=SALE                           | 1                    | 0                      | 0          | 1        | 1        |
| serviceType=SALE&propertyType=HOUSE        | 1                    | 1                      | 0          | 2        | 2        |
| serviceType=SALE&propertyType=HOUSE&city=1 | 1                    | 1                      | 1          | 3        | 3        |

см. demo

Вы также можете поместить вывод столбца в предложение HAVING, чтобы не выводить эти столбцы.См. демо

Примечание Это не будет масштабироваться в больших таблицах, скорее всего, запрос регулярного выражения также не будет масштабироваться, потому что индексы, скорее всего, не могут быть использованы.

Обходным методом может быть использование временной таблицы с правильным индексом и использование первогозапросить предварительное заполнение и выполнить условное агрегирование для временной таблицы, которая индексируется.

0 голосов
/ 16 апреля 2019

Похоже, что вы хотите, чтобы строка соответствовала всем парам значений ключа, а не любым, что соответствует текущему шаблону.

Попробуйте AND с операциями REGEXP, по одной для каждойпара ключ-значение.

s.query REGEXP '(&|^)serviceType=SALE(&|$)'
        AND s.query REGEXP '(&|^)propertyType=HOUSE(&|$)'
        AND s.query REGEXP '(&|^)city=1(&|$)'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...