ПОИСК_В_НАБОРЕ в нескольких столбцах

#mysql #sql

#mysql #sql

Вопрос:

У меня есть таблицы, как показано ниже:

 CREATE TABLE `event` (
  `id` int(11) NOT NULL,
  `name` text CHARACTER SET utf8 NOT NULL,
  `extra_info` text CHARACTER SET utf8,
  `category` text CHARACTER SET utf8,
  `date` datetime NOT NULL,
  `is_deleted` int(11) NOT NULL
);

INSERT INTO `event` 
    (`id`, `name`, `extra_info`, `category`, `date`, `is_deleted`) VALUES
    ('1', 'EVENT1', 'dog', 'other','2020-08-21 12:25:48', '0'),
    ('2', 'EVENT2', 'cat', 'sport','2020-08-21 12:25:48', '0'),
    ('3', 'EVENT3', 'fruit', 'sport','2020-08-21 12:25:48', '0'),
    ('4', 'EVENT4', 'coffee', 'sport','2020-08-21 12:25:48', '0'),
    ('5', 'EVENT5', '', 'sport','2020-08-21 12:25:48', '0'),
    ('6', 'EVENT6', '', 'sport','2020-08-21 12:25:48', '0'),
    ('7', 'EVENT7', '', 'other','2020-08-21 12:25:48', '0'),
    ('8', 'EVENT8', '', 'sport','2020-08-21 12:25:48', '0');


CREATE TABLE `event_has_keyword` (
  `event_id` int(11) NOT NULL,
  `keyword_id` int(11) NOT NULL
);

INSERT INTO `event_has_keyword` 
    (`event_id`, `keyword_id`) 
VALUES
    ('3', '4'),
    ('6','2'),
    ('8', '1'),
    ('6','6'),
    ('8', '2'),
    ('6','3'),
    ('1','4'),
    ('3', '3');
    

CREATE TABLE `event_keywords` (
  `id` int(11) NOT NULL,
  `name` text CHARACTER SET utf8 NOT NULL,
  `is_deleted` int(11) NOT NULL
); 

INSERT INTO `event_keywords` 
    (`id`, `name`, `is_deleted`) 
VALUES
    ('1', 'labrador', '0'),
    ('2', 'dog', '0'),
    ('3', 'cat with space', '0'),
    ('4', 'keyword1', '0'),
    ('5', 'keyword2', '0'),
    ('6', 'keyword3', '0');
  

Что я пытаюсь сделать, так это найти все события, в которых КАТЕГОРИЯ, EXTRA_INFO или КЛЮЧЕВОЕ СЛОВО соответствуют заданному запросу.

 SELECT E.*, K.`name` AS keywords, GROUP_CONCAT(K.`name`) AS keywords
       FROM `event` E 
       LEFT JOIN `event_has_keyword` EK 
            ON E.`id` = EK.`event_id`     
       LEFT JOIN event_keywords K
            ON EK.`keyword_id` = K.`id`
       WHERE E.`is_deleted` = 0 
            AND FIND_IN_SET (K.`name` , 'labrador,dog,cat,cat with space,other') 
            OR FIND_IN_SET (E.`category` , 'labrador,dog,cat,cat with space,other') 
            OR FIND_IN_SET (E.`extra_info` , 'labrador,dog,cat,cat with space,other')
       GROUP BY E.`id`
       ORDER BY 1 ASC
  

Мне нужно объединить FIND_IN_SET для работы со всеми столбцами K.'name' , E.'category' а E.'extra_info' не только с одним.
Поэтому, когда я ищу «лабрадор, собака, кошка с пробелом, другое», я должен найти все события, где:

K.'name' является ли лабрадор или собака или кошка или кошка с пробелом или другое и
все события, где E.'category' является лабрадор или собака или кошка или кошка с пробелом или другое и
все события, где E.'extra_info' является лабрадор или собака или кошка или кошка с пробелом или другое

В следующем случае я должен получить:

  ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| id | name   | extra_info | category | date                | is_deleted | keywords                      |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 1  | EVENT1 | dog        | other    | 2020-08-21 12:25:48 | 0          | keyword1                      |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 2  | EVENT2 | cat        | sport    | 2020-08-21 12:25:48 | 0          |                               |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 3  | EVENT3 | fruit      | sport    | 2020-08-21 12:25:48 | 0          | keyword1, cat with space      |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 6  | EVENT6 |            | sport    | 2020-08-21 12:25:48 | 0          | dog, keyword3, cat with space |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 7  | EVENT7 |            | other    | 2020-08-21 12:25:48 | 0          |                               |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 8  | EVENT8 |            | sport    | 2020-08-21 12:25:48 | 0          | labrador, dog                 |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
  

но я все еще получаю только:

  ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| id | name   | extra_info | category | date                | is_deleted | keywords                      |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 3  | EVENT3 | fruit      | sport    | 2020-08-21 12:25:48 | 0          | keyword1, cat with space      |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 6  | EVENT6 |            | sport    | 2020-08-21 12:25:48 | 0          | dog, keyword3, cat with space |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
| 8  | EVENT8 |            | sport    | 2020-08-21 12:25:48 | 0          | labrador, dog                 |
 ---- -------- ------------ ---------- --------------------- ------------ ------------------------------- 
  

таким образом, он выполняет поиск только по ключевым словам K.'name' и игнорирует E.'category' и E.'extra_info'

при попытке добавить скобки:

 WHERE E.`is_deleted` = 0 
    AND (FIND_IN_SET (K.`name` , 'labrador,dog,cat,cat with space,other') 
    OR FIND_IN_SET (E.`category` , 'labrador,cat,dog,cat with space,other') 
    OR FIND_IN_SET (E.`extra_info` , 'labrador,cat,dog,cat with space,other'))
  

возвращает значение null

Спасибо!

Комментарии:

1. У вас есть какая-либо ошибка или несоответствие результата? пожалуйста, добавьте ожидаемый результат

2. Спасибо! отредактированный вопрос

3. Используйте IN вместо find_in_set

4. Я не могу получить результаты из вашего текущего запроса с помощью этого примера данных. Можете ли вы создать скрипку: dbfiddle.uk/?rdbms=mysql_5.7 с вашими образцами данных и результатами, которые возвращает ваш текущий запрос?

5. Две проблемы: оператор Insert для оператора event has ; in between, поэтому некоторые записи не вставлены, и, во-вторых, почему вы ожидаете, что идентификатор события 2 в результирующем наборе?

Ответ №1:

cat и cat with space не являются одной и той же строкой. Вы должны добавить cat отдельно, чтобы найти в наборе. Здесь sqlfiddle работает в соответствии с вашим желанием.

 SELECT E.*, K.`name` AS keywords, GROUP_CONCAT(K.`name`) AS keywords
   FROM `event` E 
   LEFT JOIN `event_has_keyword` EK 
        ON E.`id` = EK.`event_id`     
   LEFT JOIN event_keywords K
        ON EK.`keyword_id` = K.`id`
   WHERE E.`is_deleted` = 0 
        AND (FIND_IN_SET (K.`name` , 'labrador,dog,cat with space,other') 
        OR FIND_IN_SET (E.`category` , 'labrador,dog,cat with space,other') 
        OR FIND_IN_SET (E.`extra_info` , 'labrador,dog,cat,cat with space,other'))
   GROUP BY E.`id`
   ORDER BY 1 ASC
  

Комментарии:

1. Спасибо! cat и cat with space была ли моя ошибка допущена при создании этого вопроса. В вашем sqlfiddle это выглядит совершенно нормально, но (что странно) на моей стороне он ищет только через K.’name’ и игнорирует E.’category’ и E.’extra_info’. Я только что заметил, что если я оставлю только AND FIND_IN_SET (E. extra_info ,: key_words) , это ничего не вернет…

2. перетасуйте порядок FIND_IN_SET и повторите попытку. возникает ли проблема каждый раз??

3. Спасибо! Я только что заметил, что если я оставлю только AND FIND_IN_SET (E.extra_info,: key_words) , это ничего не вернет…

4. Добро пожаловать. Вот почему я сказал, что cat и cat with space являются отдельными

5. Я проверил в sqlfiddle. Он не пустой