Обходной путь без использования регулярных выражений, этот пост только для того, чтобы показать, что это возможно.Хитрость заключается в том, чтобы создать генератор чисел 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
, чтобы не выводить эти столбцы.См. демо
Примечание Это не будет масштабироваться в больших таблицах, скорее всего, запрос регулярного выражения также не будет масштабироваться, потому что индексы, скорее всего, не могут быть использованы.
Обходным методом может быть использование временной таблицы с правильным индексом и использование первогозапросить предварительное заполнение и выполнить условное агрегирование для временной таблицы, которая индексируется.