Поиск GROUP_CONCAT для фильтрации данных - PullRequest
0 голосов
/ 26 марта 2020

Я хочу иметь возможность искать свои продукты (искать по названию продукта или по коду продукта), а затем фильтровать и эти результаты.

Я не знаю, что искать для в Google или SO, каждый раз, когда я получаю Поиск GROUP_CONCAT с использованием LIKE или Php и MySQL GROUP_CONCAT с запятой-разделителем и поиска, где появляются конкат по запятой , но я могу Кажется, я не могу обернуться вокруг HAVING без ошибки в моей базе данных. Я не уверен, возможно ли это вообще или я просто в отъезде.

Мои столы такие:

Таблица продуктов

+------------+--------------+----------------+-------------------------+---------------+
| product_id | product_name | product_status | product_date_available  | product_type  |
+------------+--------------+----------------+-------------------------+---------------+
|          1 | Rug          |              1 | 2020-01-24              |             0 |
|          2 | Scraper      |              1 | 2020-03-15              |             0 |
|          3 | Shovel       |              0 | 2019-04-24              |             0 |
|          4 | Bucket       |              1 | 2030-01-01              |             0 |
|          5 | Dog          |              1 | 2018-04-27              |             0 |
|          6 | Digging      |              1 | 2020-01-01              |             1 |
+------------+--------------+----------------+-------------------------+---------------+

Таблица категорий продуктов

+------------+-------------+
| product_id | category_id |
+------------+-------------+
|          1 |          17 |
|          2 |          22 |
|          3 |          22 |
|          4 |          17 |
+------------+-------------+

Таблица тегов продуктов

+------------+--------+
| product_id | tag_id |
+------------+--------+
|          1 |     11 |
|          2 |      6 |
|          3 |      7 |
|          4 |      7 |
+------------+--------+

Таблица кодов продуктов

+---------+------------+------------+
| code_id | product_id | code_value |
+---------+------------+------------+
|       1 |          1 | 47012.000  |
|       2 |          1 | 47012.001  |
|       3 |          2 | 47013.000  |
|       4 |          3 | 47014.000  |
|       5 |          3 | 47014.001  |
|       6 |          3 | 47014.002  |
+---------+------------+------------+

Таблица значений вариантов продукта

+-------+------------+----------+
| pv_id | product_id | value_id |
+-------+------------+----------+
|     1 |          1 |        7 |
|     2 |          1 |        6 |
|     3 |          1 |       10 |
|     4 |          2 |        7 |
|     5 |          3 |       10 |
|     6 |          3 |        7 |
|     7 |          3 |       12 |
|     8 |          2 |       14 |
+-------+------------+----------+

Это то, что я пробовал, но не могу получить работу:

Поиск по коду продукта

SELECT p.product_id,
  (SELECT GROUP_CONCAT(DISTINCT code_value) FROM `me_product_variant_codes` WHERE `product_id` = p.product_id) AS codes,
  (SELECT GROUP_CONCAT(DISTINCT value_id) FROM `me_product_variant_values` WHERE `product_id` = p.product_id) AS variant_values,
  (SELECT GROUP_CONCAT(DISTINCT tag_id) FROM `me_product_tags` WHERE `product_id` = p.product_id) AS product_tags
    FROM me_product AS p
    WHERE (p.product_status = '1' AND p.product_date_available <= CONVERT_TZ(NOW(), 'SYSTEM', '+13:00') AND p.product_type = '0')
    AND ((LOWER(p.product_name) LIKE '%47012%')
    GROUP BY p.product_id
    HAVING codes LIKE '%47012%'
    AND HAVING variant_values IN(7, 10)
    AND HAVING product_tags IN(11)
    ORDER BY product_name DESC
    LIMIT 24

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

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

+------------+----------------------+----------------+--------------+
| product_id |        codes         | variant_values | product_tags |
+------------+----------------------+----------------+--------------+
|          1 | 47012.000, 47012.001 | 7, 6           |           11 |
+------------+----------------------+----------------+--------------+

Но я в настоящее время получаю эту ошибку

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'GROUP BY p.product_id
    HAVING codes LIKE '%47012%'
    AND HAVING variant_v' at line 8

Даже попытка простой версии моего запроса хотя бы получить какой-либо результат дает мне ошибку

Упрощенный запрос

SELECT p.product_id,
  (SELECT GROUP_CONCAT(DISTINCT code_value) FROM `me_product_variant_codes` WHERE `code_product_id` = p.product_id) AS codes
    FROM me_product AS p
    WHERE (p.product_status = '1' AND p.product_date_available <= CONVERT_TZ(NOW(), 'SYSTEM', '+13:00') AND p.product_type = '0')
    AND ((LOWER(p.product_name) LIKE '%47012%')
    GROUP BY p.product_id
    HAVING codes LIKE '%47012%'
    ORDER BY p.product_name DESC
    LIMIT 24

дает мне эта ошибка

#1064 - You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'GROUP BY p.product_id
    HAVING codes LIKE '%47012%'
    ORDER BY p.product_n' at line 6

Другая проблема, которую я только что заметил, заключается в том, что я не уверен, как это будет возвращать результаты, если оно соответствует product_name ИЛИ одному из codes значений

1 Ответ

3 голосов
/ 26 марта 2020

Вы должны избавиться от всех этих взаимосвязанных подзапросов и вместо этого использовать соединения с подзапросами, которые вычисляют различные термины CSV:

SELECT
    p.product_id,
    COALESCE(vc.codes, 'NA') AS codes,
    COALESCE(vv.variant_values, 'NA') AS variant_values,
    COALESCE(pt.product_tags, 'NA') AS product_tags
FROM me_product AS p
LEFT JOIN
(
    SELECT product_id, GROUP_CONCAT(DISTINCT code_value) AS codes
    FROM me_product_variant_codes
    WHERE code_value LIKE '%47012%'
    GROUP BY product_id
) vc
    ON vc.product_id = p.product_id
LEFT JOIN
(
    SELECT product_id, GROUP_CONCAT(DISTINCT value_id) AS variant_values
    FROM me_product_variant_values
    GROUP BY product_id
    HAVING COUNT(CASE WHEN value_id = 7 THEN 1 END) > 0 AND
           COUNT(CASE WHEN value_id = 10 THEN 1 END) > 0
) vv
    ON vv.product_id = p.product_id
LEFT JOIN
(
    SELECT product_id, GROUP_CONCAT(DISTINCT tag_id) AS product_tags
    FROM me_product_tags
    GROUP BY product_id
    HAVING COUNT(CASE WHEN tag_id = 11 THEN 1 END) > 0
) pt
    ON pt.product_id = p.product_id
WHERE
    p.product_status = '1' AND
    p.product_date_available <= CONVERT_TZ(NOW(), 'SYSTEM', '+13:00') AND
    p.product_type = '0' AND
    LOWER(p.product_name) LIKE '%47012%';
...