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

Я работаю над этой проблемой в течение 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 ]

0 голосов
/ 04 сентября 2018

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

поле [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)

Песочница

P.S. внедрение 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.

Ура!

0 голосов
/ 04 сентября 2018

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

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