Я использовал следующий запрос:

Я использую две таблицы: (есть некоторые другие, упомянутые, но не нужные для этого вопроса)

assessment_criteria
+-------------------+--------------+------+-----+---------+----------------+
| Field             | Type         | Null | Key | Default | Extra          |
+-------------------+--------------+------+-----+---------+----------------+
| id                | mediumint(9) | NO   | PRI | NULL    | auto_increment |
| scheme_of_work_id | mediumint(9) | NO   |     | NULL    |                |
| level             | char(255)    | YES  |     | NULL    |                |
| criteria          | char(255)    | NO   |     | NULL    |                |
+-------------------+--------------+------+-----+---------+----------------+

criteria_completed
+------------------------+--------------+------+-----+---------+----------------+
| Field                  | Type         | Null | Key | Default | Extra          |
+------------------------+--------------+------+-----+---------+----------------+
| id                     | mediumint(9) | NO   | PRI | NULL    | auto_increment |
| student_ID             | mediumint(9) | NO   |     | NULL    |                |
| assessment_criteria_id | mediumint(9) | NO   |     | NULL    |                |
| date_marked            | date         | NO   |     | NULL    |                |
| notes                  | varchar(255) | YES  |     | NULL    |                |
| attainment             | varchar(15)  | YES  |     | NULL    |                |
| effort                 | varchar(15)  | YES  |     | NULL    |                |
| marked_by              | varchar(20)  | NO   |     | NULL    |                |
+------------------------+--------------+------+-----+---------+----------------+

Я использовал подобный запрос, чтобы отобразить список критериев оценки, которые студент НЕ выполнил:

SELECT DISTINCT assessment_criteria.id, assessment_criteria.level, assessment_criteria.criteria FROM assessment_criteria, criteria_completed  
WHERE (assessment_criteria.scheme_of_work_id = '17') 
AND (assessment_criteria.id NOT IN (SELECT criteria_completed.assessment_criteria_id FROM criteria_completed WHERE (student_ID = '403'))) 
ORDER BY level;

Этот запрос стал невероятно медленным для выполнения, я пытался сделать его быстрее, используя LEFT JOIN.

SELECT DISTINCT a.id, a.level, a.criteria 
FROM assessment_criteria a
LEFT JOIN criteria_completed b
ON a.id = b.assessment_criteria_id
WHERE b.assessment_criteria_id IS NULL

Но у меня ничего не получается, когда я пытаюсь добавить пункты для проекта и студента; т.е.

SELECT DISTINCT a.id, a.level, a.criteria 
FROM assessment_criteria a
LEFT JOIN criteria_completed b
ON a.id = b.assessment_criteria_id
WHERE b.assessment_criteria_id IS NULL
AND (b.student_ID = '403')
AND (a.scheme_of_work_id = '17');

Mysql сообщает о «пустом наборе». Я подозреваю, что неправильно ссылаюсь на эти внешние ключи?

3
ICT Teacher 22 Янв 2014 в 19:04

1 ответ

Лучший ответ

(Для подтверждения, вы используете b.assessment_criteria_id IS NULL для обнаружения неудачных соединений)

Применение фильтров к таблице b к предложению WHERE отфильтрует любые записи, в которых соединение не удалось, что, как я считаю, является причиной проблемы.

Вы можете попробовать переместить фильтры b в условие JOIN:

SELECT DISTINCT a.id, a.level, a.criteria 
FROM assessment_criteria a
LEFT JOIN criteria_completed b
  ON a.id = b.assessment_criteria_id
  AND (b.student_ID = 403)
WHERE b.assessment_criteria_id IS NULL
  AND (a.scheme_of_work_id = 17);

Хотя лично мне не нравится подобная фильтрация в JOIN . Альтернативой может быть:

SELECT DISTINCT a.id, a.level, a.criteria 
FROM assessment_criteria a
LEFT JOIN criteria_completed b
  ON a.id = b.assessment_criteria_id
WHERE (a.scheme_of_work_id = 17)
   AND (b.assessment_criteria_id IS NULL OR b.student_ID = 403);
1
Community 23 Май 2017 в 15:03
Спасибо. Похоже, здесь перечислены все записи из Assessment_criteria, а не только для scheme_of_work_ID = 17.
 – 
ICT Teacher
22 Янв 2014 в 19:16
На самом деле странно, но он отлично работает как запрос в mysql, но как только я делаю это с PHP, на выполнение запроса уходит много времени. : -S
 – 
ICT Teacher
22 Янв 2014 в 19:34
Просто контрольный список: вам понадобятся индексы по a.scheme_of_work_id, FK b.assessment_criteria_id и b.student_ID. Также обратите внимание, что все столбцы id являются целыми - это сэкономит цикл ЦП или 2, удалив кавычки :)
 – 
StuartLC
22 Янв 2014 в 19:39
Да, я все время слышу об этих индексных штуках. Я полагаю, они все-таки должны быть важны. Сделаю еще немного чтения. Еще раз спасибо.
 – 
ICT Teacher
22 Янв 2014 в 19:55