MySQL - Как выбрать строки в таблице, где значение id находится в поле с разделителями-запятыми в другой таблице?

Я работаю над этой проблемой в течение 3 дней, и у меня мутные глаза. У меня есть таблица SQL "клиенты", содержащая имя клиента, адрес, адрес электронной почты и поле с именем "место проведения", содержащее набор разделенных запятыми идентификаторов мест проведения учебных курсов, в которых они заинтересованы. (Например: 18,22,35,41)

У меня есть второй стол под названием "Место проведения", в котором находятся места проведения всех курсов. Каждый курс представляет собой отдельную строку в таблице "место проведения" с идентификатором автоинкремента. Поле места в таблице "клиенты" представляет собой набор строки "id" в таблице места, которую клиент выбрал при регистрации.

После того, как клиент зарегистрирован и перенесен на страницу "мои интересы", я хотел бы отобразить курсы, в которых он зарегистрировал интерес, путем вывода данных строк каждого "id" таблицы "место проведения", которые содержатся в " customer.venue "поле таблицы клиента.

Надеюсь это имеет смысл...

Мой клиент выбирает

$sqlc = "Select * from customers ORDER BY id DESC LIMIT 1";

Мой выбор места

$venue = $result['venue'];

Мой текущий код выбора места проведения, который не работает

sqlcp = "SELECT * FROM venue WHERE FIND_IN_SET('$venue', id)";

Пожалуйста, задавайте любые вопросы, спасибо за внимание

2 ответа

Решение

Я думаю, что вы должны написать этот код как:

$sqlcp = "SELECT * FROM venue WHERE FIND_IN_SET(id,'$venue')";

Теперь, если я не понимаю вопрос:

поле [input] называется "место встречи", содержащее набор, разделенный запятыми

Другими словами мы можем сказать $result['venue'] как 1,2,3,4,

И тогда этот бит:

У меня есть второй стол под названием "Место проведения", в котором находятся места проведения всех курсов. Каждый курс - это отдельный ряд

Другими словами, мы можем сказать, что id является первичным ключом места.

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

Конечно, вы можете просто вставить их в запрос в этом случае (для идентификаторов не нужны кавычки в IN), но это не дает вам никакой защиты от сбоев.

Например:

  //Please don't do this as you can get SQLInjection from the input
  $sql = "SELECT * FROM venue WHERE id IN (".$result['venue'].")";

Вместо этого сделайте что-то вроде этого:

   $venue = implode(',',array_map('intval',array_filter(array_map('trim', explode(',',$result['venue'])))));

   $sql = "SELECT * FROM venue WHERE id IN (".$venue.")";

Обычно я бы не стал объединять, но, пожалуйста, примите к сведению array_map('intval', ..) который преобразует их в целые.

Чтобы объяснить, что все это делает с массивом (по порядку):

  1. взорваться ,
  2. обрезать пустое пространство, такое как , запятая оставит пробел
  3. Фильтр удалит все ложные элементы, такие как ,, пустая заметка 0 является частью этого
  4. преобразовать тип в int по нескольким причинам.
  5. тогда мы снова взрываемся.

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

 $v="1,,2 , 4); DROP TABLE users --";

 echo "Unsafe:\n";
 echo "SELECT * FROM venue WHERE id IN ({$v})\n\n";

 $venue = implode(',',array_map('intval',array_filter(array_map('trim', explode(',',$v)))));

 print_r($venue);

 echo "Safer:\n";
 echo "SELECT * FROM venue WHERE id IN ({$venue})\n\n";

Выход

 Unsafe:
 SELECT * FROM venue WHERE id IN (1,,2 , 4); DROP TABLE users --)

 Safer:
 SELECT * FROM venue WHERE id IN (1,2,4)

песочница

PS Mutli-запрос инъекций, вероятно, не будет работать в любом случае с "современной" версией PHP, но это только один пример

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

Я думаю, что вы слишком усложнили это.

@ Таха Аскари прав, у вас есть аргументы задом наперед. Это простая ошибка, потому что она предназначена для поиска в базе данных, которая находится в списке. Не наоборот или, по крайней мере, это обычный способ его использования.

Пример таков:

     //this is the correct way
     SELECT * FROM venue WHERE FIND_IN_SET(1,'1,2,3,4')
     //this is the way you have it
     SELECT * FROM venue WHERE FIND_IN_SET('1,2,3,4', 1)

Для справки FIND_IN_SET

Тем не менее, нам не нужно использовать FIND_IN_SET в этом случае, потому что мы можем просто использовать IN, который является более "правильным" в этом случае.

И последнее, если бы они хранились в отдельной таблице с отношением к клиенту, все это можно было бы сделать в MySql. Данные CSV в БД обычно плохо работают. Все, что вам нужно, это таблица с 2 столбцами.

 //table customers_venues
  customer_id
  venue_id

Тогда вы могли бы сделать запрос, как это:

    Select 
        cv.venue
    from
        customers AS c
    JOIN
        customers_venues AS cv ON cv.customer_id = c.id
    JOIN
        venues as v ON cv.venue_id = v.id

Но я не знаю, что сказать LIMIT 1,

Ура!

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