Поиск значений с разделителями-запятыми в базе данных с запросом SELECT MYSQL

У меня проблема с получением результатов из базы данных. У меня есть столбец под названием «Регионы», который в качестве значения содержит все регионы, выбранные пользователем через форму подписки на информационный бюллетень, с запятыми, например «Ближний Восток, Европа».

Я создаю фильтр, который должен будет получить список всех пользователей, которые регистрируются в определенном или нескольких регионах. Пользователи могут выбрать несколько регионов. Из внешнего интерфейса я получаю все выбранные регионы в этом формате «Глобальный, Ближний Восток», который мне нужно использовать в моем SQL-запросе, чтобы найти всех пользователей, у которых глобальный и Ближний Восток выбран в качестве выбранного региона.

Я пытался использовать FIND_IN_SET, но это не очень помогает. Пробовал ниже

 $trimmedRegions = rtrim($sortType,', ');

 $query = "SELECT * FROM health_alerts_subscribers
            WHERE FIND_IN_SET(Regions, $trimmedRegions)";

Любые идеи, как я могу добиться необходимого результата, пожалуйста?

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

RiggsFolly 22.02.2019 16:00
"значение содержит все регионы, выбранные пользователем через форму подписки на рассылку новостей, с запятыми" - Я думаю, вы сейчас сожалеете об этом дизайнерском решении. «Данные зависят от ключа [1NF], всего ключа [2NF] и ничего, кроме ключа [3NF], так что помогите мне Кодд». Как ни странно, результат №1 в Google по запросу «ключ, весь ключ и ничего, кроме» приводит к еще одному SO вопрос о нормализации данных.
CD001 22.02.2019 16:00

FIND_IN_SET должен работать. Можете ли вы поделиться, как он использовался и как он работал? Я бы пошел по нормализованному маршруту, данные с разделителями всегда будут вызывать проблемы.

user3783243 22.02.2019 16:04

@user3783243 user3783243 я обновил свой вопрос. Итак, вы предлагаете хранить все регионы отдельно и иметь такие значения, как «да» или «нет»?

Anahit DEV 22.02.2019 16:15

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

Vidal 22.02.2019 16:16

@ Видал, что, если у меня есть несколько вариантов фильтра, таких как «Глобальный» и «Европа»?

Anahit DEV 22.02.2019 16:21

см. мой ответ, вы делаете 2 лайка, где регион похож ("%Global%") и регион похож ("%Europe%")

Vidal 22.02.2019 16:22

Вам нужен FIND_IN_SET для каждого отдельного значения. WHERE FIND_IN_SET(Regions, 'Middle East') and FIND_IN_SET(Regions, 'Global'). Я бы сделал другую таблицу, которая имеет отношение к каждой записи.

user3783243 22.02.2019 16:35
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
1
8
58
4
Перейти к ответу Данный вопрос помечен как решенный

Ответы 4

Вам в значительной степени нужно отформатировать свой sql следующим образом:

SELECT
    *
FROM
    table
WHERE
    regions = 'Europe' or
    regions like 'Europe,%' or
    regions like '%,Europe' or
    regions like '%,Europe,%' or
    regions = 'Middle East' or
    regions like 'Middle East,%' or
    regions like '%,Middle East' or
    regions like '%,Middle East,%'

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

Зачем столько лайков, можно поставить один вайлд и в начале и другой в конце. как "%значение%"

Vidal 22.02.2019 16:14

@Vidal Я понятия не имею, как выглядит полный список регионов, поэтому, если regions содержит что-то вроде Global,Middle East,Europe,East,Asia, то %East% вернет слишком много результатов.

MonkeyZeus 22.02.2019 16:29

@Vidal Я уверен, что всю эту ситуацию можно REGEXP_LIKE() решить, но у меня нет терпения, чтобы понять это для OP. Они должны нормализовать свои таблицы и жить дальше. Это будет настоящее дерьмовое шоу, если регион когда-нибудь изменит свое название, заглавные буквы или разделится на несколько регионов или что-то в этом роде.

MonkeyZeus 22.02.2019 16:35

Я могу предложить такой подход.

SELECT * FROM table
WHERE 
   region like("%Global%")
   and region like ("%Middle East%")

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

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

Anahit DEV 22.02.2019 16:24

Вы хотите получить список подписчиков, чтобы отправить электронное письмо? какова цель увидеть, могу ли я дать вам лучший ответ?

Vidal 22.02.2019 16:27

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

Anahit DEV 22.02.2019 16:28

хорошо, вы можете сделать запрос [SELECT * FROM table WHERE region like("%Global%")] и получить всех глобальных подписчиков, а затем сохранить их в глобальном списке рассылки, затем сделать запрос для следующего региона Ближний Восток и сын на.

Vidal 22.02.2019 16:32

хорошо, но что мне делать с пользователями, у которых несколько регионов в качестве значения? Одним запросом это не приведет к тому, что пользователи

Anahit DEV 22.02.2019 16:33

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

Vidal 22.02.2019 16:35

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

Anahit DEV 22.02.2019 16:40

ОК, теперь я в замешательстве, если вы собираетесь отправить пользователю его / ее регионы, просто запросите таблицу без какого-либо фильтра «где» или «регион». Что вы хотите получить от стола? Какова цель, если вы можете поделиться этим?

Vidal 22.02.2019 16:43

Мне нужно отправить пользователю по электронной почте новости о выбранных им регионах, поэтому мне нужно знать, какие пользователи, например, для Европы и Азии, поэтому я экспортирую этот список

Anahit DEV 22.02.2019 16:45

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

Vidal 22.02.2019 16:47

Хорошо, тогда мой 4-й комментарий — это то, что вам нужно. Вам нужно будет сделать запрос для каждого региона.

Vidal 22.02.2019 16:49
Ответ принят как подходящий

Я рекомендую то, что говорит пользователь 3783243. Я бы выбрал FIND_IN_SET. Вот пример.

SELECT {columns} FROM {table} WHERE FIND_IN_SET({item_to_search}, {comma-delimited column})

Лучшим способом было бы создать таблицу регионы и добавить свои регионы, а затем создать связанную таблицу с именем regionRelation (пример), а затем добавить идентификатор из региона и таблицы ссылок (как многие ко многим)

Table structure example

Table region
id,region
1, Middle East
2, Global

Table user
id,name
1, John
2, Jan

Table userRegion
userId,regionId
1,1
2,1

SELECT user.id,user.name,region.region from user
left join userRegion ON region.userId=user.id
left  join region
where region.region in('Middle East','Global');

В раскрывающемся списке просто выберите все регионы, и когда пользователь выберет те, которые ему нужны, вы сохраните их в таблице пользовательРегион с INSERT INTO userRegion (userid,regionId) (1,2); и так далее.

на место item_to_search что поставить? строка с выбранными областями, разделенными запятыми? и {столбец с разделителями-запятыми} указать имя столбца?

Anahit DEV 22.02.2019 16:23

Так вы рекомендуете или нет?

Strawberry 22.02.2019 16:33

Если у меня будет каждый регион в виде отдельного столбца со значением «да» или «нет», решит ли это мою проблему?

Anahit DEV 22.02.2019 16:38

Анаит, тогда вам придется добавлять новый столбец для каждого нового региона. Это не правильный путь. Я рекомендую свой пример выше.

blupointmedia 22.02.2019 16:40

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

blupointmedia 22.02.2019 16:42

Дело в том, что Регионы фиксированы, их 6 Глобальный, Африка, Средний Восток, Америка, Азия и Европа.

Anahit DEV 22.02.2019 16:44

Вы тоже пойдете по этому пути. Технически их 8. Я бы создал логический столбец для каждого и 1 для да/истина и 0 для нет/ложь

blupointmedia 22.02.2019 16:46

Хорошо, и тогда мой запрос будет похож на select, где значение равно 1?

Anahit DEV 22.02.2019 16:53

ВЫБЕРИТЕ {столбцы} из {таблицы}, ГДЕ Африка = 1 ИЛИ Азия = 1 и т. д. Вам нужно будет построить запрос на основе выбора пользователя

blupointmedia 22.02.2019 16:55

Если это сработает, пожалуйста, примите ответ. Спасибо и удачи.

blupointmedia 22.02.2019 17:11

Сработало :) Большое спасибо

Anahit DEV 22.02.2019 18:48

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

$trimmedRegions = rtrim($sortType,', ');
$trimmedRegionsCollection = explode(",", $trimmedRegions);
$trimmedRegionsRegex = implode("|", $trimmedRegionsCollection); // make string like Global|Middle East

$query = 'SELECT * from health_alerts_subscribers WHERE CONCAT(",", `Regions`, ",") REGEXP ",('.$trimmedRegionsRegex.'),"';

Надеюсь, это поможет вам.

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