Оператор MySQL IN() не работает
Как использовать оператор IN() не работает это.
Эти таблицы являются примерами и выглядят так же, как реальная база данных, которую я имею.У меня нет разрешения на добавление таблиц или изменение
Это таблицы:
students
+------+------+
| id | name |
+------+------+
| 1 | ali |
| 2 | man |
| 3 | sos |
+------+------+
Classes
+------+---------+
| c_id | students|
+------+---------+
| 1 | 1,2,3,4 |
| 2 | 88,33,55|
| 3 | 45,23,72|
+------+---------+
Когда я использую этот запрос, он возвращает мне только студента с id =1, потому что "id IN (Students)" возвращает 1, когда первое значение равно.
select name,c_id from students,classes where id IN (students);
когда я получу список на PHP, чем добавить его. это работает нормально. Но это решение нуждается в цикле и стоит много запросов.
select name,c_id from students,classes where id IN (1,2,3,4);
FIND_IN_SET ()
произошло то же самое, он возвращает только 1, но если значение в другой позиции, он возвращает 0.
3 ответа
IN
Оператор работает отлично, где это применимо для того, что он делает.
Во-первых, рассмотрите возможность нормализации ваших данных и избегайте хранения значений в виде разделенных запятыми списков.
Во-вторых, если вам абсолютно необходимо иметь дело со столбцами, содержащими разделенные запятыми списки значений, MySQL предоставляет FIND_IN_SET()
функция.
СЛЕДОВАТЬ ЗА
Отключите синтаксис запятой старой школы для операции соединения и используйте JOIN
ключевое слово вместо И переместите предикаты объединения из предложения WHERE в предложение ON. Полностью квалифицировать ссылки на столбцы, например.
SELECT s.name
, c.c_id
FROM students s
JOIN classes c
ON FIND_IN_SET(s.student_id,c.students)
ORDER BY s.name, c.c_id
Повторим еще раз: сохранение "списка через запятую" в столбце - это не шаблон; он противоречит реляционной теории и нормализации и игнорирует лучшие практики в отношении реляционных баз данных. О
Кто-то может поспорить за улучшение производительности, но этот шаблон не улучшает производительность; скорее это добавляет ненужную сложность в запрос и операции DML.
Вам нужно три стола. Один стол students
один стол classes
и затем один стол, скажем, students_to_classes
содержащий что-то вроде
c_id | student_id
1 | 1
1 | 2
1 | 3
1 | 4
2 | 88
и так далее. Тогда вы можете запросить
select c_id from students_to_classes where student_id in (1,2,3,4)
Google "отношения n: m" для фона на этом.
РЕДАКТИРОВАТЬ
Я знаю, что вы специально не запрашиваете другую структуру таблицы, но это способ иметь тип данных (одно число), который работает с IN
, Пожалуйста, поверьте мне, это правильный способ сделать это, потому что у вас возникли проблемы с чем-то простым IN
в том, что вы используете нестандартный подход, который для такой стандартной проблемы, как правило, не очень хорошая идея.
Это не то, как должна работать функция IN. Вы используете IN, когда у вас есть список возможных совпадений, таких как:
вместо:
WHERE id=1 or id=2 or id=3 or id=4
ты используешь:
WHERE id IN (1,2,3,4)
Во всяком случае, ваша логика не верна. Соотношение класса и ученика - "многие ко многим", поэтому необходима третья таблица. Давайте назовем это studend_class
где вы можете хранить ученики каждого класса.
student
+------+------+
| id | name |
+------+------+
| 1 | ali |
| 2 | man |
| 3 | sos |
+------+------+
class
+------+---------+
| id | name |
+------+---------+
| 1 | math |
| 2 | english |
| 3 | science |
+------+---------+
student_class
+------------+-------------+
| class_id | student_id |
+------------+-------------+
| 1 | 1 |
| 1 | 2 |
| 1 | 3 |
| 3 | 3 |
+--------------+-----------+
В приведенном выше примере все учащиеся находятся в классе по математике, а также в классе по естествознанию.
Наконец, если вы хотите узнать, какие студенты в каком классе, скажем, по математике, вы можете использовать:
SELECT s.id, s.name, c.name
FROM student s
INNER JOIN student_class sc ON sc.student_id=s.id
INNER JOIN class c ON sc.class_id = c.id
WHERE c.name="math";