Как проверить, существует ли значение из строки, разделенной запятыми, в строке MySQL

У меня есть таблица со столбцом с именем tags. В этом столбце у меня есть список, разделенный запятыми, например air conditioner, tv, fridge.

Я хочу проверить, существует ли какое-либо слово в столбце, разделенном запятыми, в строке типа

Is there an air conditioner in the room?

Итак, запрос должен вернуть совпадение, как в столбце tags, значение air conditioner существует.

Я думал использовать find_in_set, но в данном случае это не сработает, поскольку логика должна быть обратной.

select * from products where find_in_set('Is there an air conditioner in the room?',tags) <> 0

ОБНОВЛЯТЬ

Я мог бы использовать find_in_set, разделив строку на слова и затем проверив столбец тегов, но это не сработает для такой комбинации, как «кондиционер», поскольку она будет выглядеть как air, conditioner.

MySQL версия 5.7.44

Не используйте список, разделенный запятыми: stackoverflow.com/questions/3653462/…

Barmar 15.04.2024 19:09

Рассматривали ли вы возможность использования полнотекстового поиска по тексту?

Salman Arshad 15.04.2024 19:18

@SalmanA Полный текст MySQL не может использовать ссылку на столбец в качестве шаблона поиска.

Bill Karwin 15.04.2024 19:27

Я уже пробовал полнотекстовый режим, но это не сработало

lStoilov 15.04.2024 20:20
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
Освоение архитектуры микросервисов с Laravel: Лучшие практики, преимущества и советы для разработчиков
В последние годы архитектура микросервисов приобрела популярность как способ построения масштабируемых и гибких приложений. Laravel , популярный PHP...
Как построить CRUD-приложение в Laravel
Как построить CRUD-приложение в Laravel
Laravel - это популярный PHP-фреймворк, который позволяет быстро и легко создавать веб-приложения. Одной из наиболее распространенных задач в...
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
Освоение PHP и управление базами данных: Создание собственной СУБД - часть II
В предыдущем посте мы создали функциональность вставки и чтения для нашей динамической СУБД. В этом посте мы собираемся реализовать функции обновления...
Документирование API с помощью Swagger на Springboot
Документирование API с помощью Swagger на Springboot
В предыдущей статье мы уже узнали, как создать Rest API с помощью Springboot и MySql .
Роли и разрешения пользователей без пакета Laravel 9
Роли и разрешения пользователей без пакета Laravel 9
Этот пост изначально был опубликован на techsolutionstuff.com .
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
Как установить LAMP Stack - Security 5/5 на виртуальную машину Azure Linux VM
В предыдущей статье мы завершили установку базы данных, для тех, кто не знает.
2
4
68
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете проверить это следующим образом:

``` 
create table mytags (
  id int(11),
  tags varchar(64)
  );

insert into mytags values(1,"air conditioner, tv, fridge");

SELECT * from mytags;


```


| id | tags |
|---:|:-----|
| 1 | air conditioner, tv, fridge |

``` 
SELECT * FROM mytags WHERE FIND_IN_SET("air conditioner",tags);
```
| id | tags |
|---:|:-----|
| 1 | air conditioner, tv, fridge |

рабочий пример

Или всегда удаляйте все пробелы. Затем вы можете найти его с пробелами или без них. Например:

```

SELECT * FROM mytags WHERE
 FIND_IN_SET(REPLACE("airconditioner"," ",""),REPLACE(tags," ",""));

| id | tags |
|---:|:-----|
| 1 | air conditioner, tv, fridge |

рабочий пример

Это нормально, но невозможно научиться разделять слова в предложении. Если мы используем пробел в качестве разделителя, он разделит air conditioner на два слова, например air и conditioner. Так что это не сработает, пока я не найду какую-то логику (разделение строки на значимые части), которая будет работать во всех случаях.

lStoilov 15.04.2024 18:56

@lStoilov - у меня в ОТВЕТЕ

Bernd Buffen 15.04.2024 19:04

Как это поможет, если строка поиска будет is there an air conditioner in the room?, а не просто air conditioner?

Barmar 15.04.2024 19:07

Кстати, после запятых не следует ставить пробел. FIND_IN_SET() относится к ним буквально.

Barmar 15.04.2024 19:08

@Бармер - спасибо за совет. Это моя ошибка

Bernd Buffen 15.04.2024 19:12
Ответ принят как подходящий
SELECT * FROM products
CROSS JOIN JSON_TABLE(CONCAT('["', REGEXP_REPLACE(tags, ', *', '","'), '"]'),
  '$[*]' COLUMNS(tag VARCHAR(20) PATH '$')
) AS j
WHERE LOCATE(j.tag, 'Is there an air conditioner in the room?');

Демо: https://dbfiddle.uk/ayNuWEqQ

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


Для приведенного выше решения с JSON_TABLE() требуется MySQL 8.0 или более поздняя версия. Срок службы MySQL 5.x уже истек, но я понимаю, что некоторые люди еще не обновились. Я оставлю этот ответ здесь для будущих людей, которые прочитают эту ветку.

Когда я пытаюсь выполнить ваш запрос, я получаю эту ошибку № 1064. У вас есть ошибка в синтаксисе SQL; проверьте руководство, соответствующее версии вашего сервера MySQL, чтобы узнать правильный синтаксис для использования рядом с '(CONCAT('["', REGEXP_REPLACE(tags, ', ', '","'), '"]'), '$[ ]' COLUMNS(тег ' в строке 2

lStoilov 15.04.2024 20:29

Возможно, потому, что я использую MySQL 5.7.44.

lStoilov 15.04.2024 20:42

Попробовал изменить версию в вашем dbfiddle, и я получил ту же ошибку.

lStoilov 15.04.2024 20:48

Что ж, вам придется либо перейти на MySQL 8.0, либо изменить структуру таблицы, чтобы избежать списков, разделенных запятыми. В этой теме вы получили два хороших ответа. Удачи.

Bill Karwin 15.04.2024 21:13

Согласен с вами... Пойду со сменой версии, так как это проще, чем структура базы данных. Спасибо.

lStoilov 15.04.2024 21:19

У меня есть еще один вопрос. Когда я пытаюсь выполнить запрос, я получаю эту ошибку #3141 - Invalid JSON text in argument 1 to function json_table: "Missing a comma or ']' after an array element." at position 271.

lStoilov 11.05.2024 08:02

Что ж, моя демо-версия dbfiddle работает (см. ссылку, которую я привел выше). Я не знаю, как выглядят ваши данные и какой запрос вы пытаетесь выполнить.

Bill Karwin 11.05.2024 08:32

Спасибо, Билл, только что понял, что проблема была в опечатке с моей стороны.

lStoilov 11.05.2024 12:10

Я обнаружил странную проблему... иногда в некоторых запросах выскакивает эта ошибка #3141 - Invalid JSON text in argument 1 to function json_table: "Invalid encoding in string." at position 429. Есть ли у вас какие-либо идеи, в чем может быть проблема? Я вижу, что проблема связана с кодировкой в ​​строке, но означает ли это кодировку ключевых слов в тегах или кодировку самого поля? Текущая кодировка поля — это utf8mb4_general_ci сопоставление таблицы после обновления до MySQL 8, которое стало utf8mb3_general_ci

lStoilov 11.05.2024 20:25

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

Bill Karwin 11.05.2024 20:39

Вот демонстрационные данные dbfiddle.uk/85sJIh77 вместе с моим запросом. Я не могу воспроизвести полученную ошибку, но запрос в образце ничего не улавливает. Данные не на английском языке, но это реальные данные.

lStoilov 11.05.2024 21:27

Я протестировал и сузил его до символа табуляции (^I), следующего за текстом JSON. Удалите символ табуляции, и все будет работать нормально.

Bill Karwin 12.05.2024 00:40

Это сделало это. Удаление всех вкладок решило проблему. Еще раз спасибо, Билл!

lStoilov 12.05.2024 06:17

Не используйте поля, разделенные запятыми. Нормализуйте свою схему, поместив теги в отдельную таблицу с внешним ключом, указывающим на таблицу products.

CREATE TABLE product_tags (
    tag VARCHAR(100),
    product_id INT,
    PRIMARY KEY (tag, product_id),
    FOREIGN KEY (product_id) REFERENCES products (id)
);

Тогда вы можете использовать

SELECT p.*
FROM products AS p
JOIN product_tags AS pt ON p.id = pt.product_id
WHERE LOCATE(pt.tag, 'Is there an air conditioner in the room?')

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

lStoilov 15.04.2024 20:21

Другие вопросы по теме