3

I have been using the following query:

I am using two tables: (there are some others mentioned but not needed for this question)

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    |                |
+------------------------+--------------+------+-----+---------+----------------+

I was using a query like this to display a list of assessment criteria that a student HAS NOT completed:

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;

This query has become incredibly slow to run, I have been trying to make it faster using 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

But I am having no success when I try to add in clauses for project and student; ie.

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 reports "empty set". I suspect I am referencing these foreign keys incorrectly?

1 Answers1

1

(Just to confirm, you are using b.assessment_criteria_id IS NULL to detect failed joins)

Applying the filters on table b to the WHERE clause will filter out any records where the join has failed, which I believe is the cause of the problem.

You can try moving the b filters into the JOIN condition:

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);

Although personally, I dislike filtering like this in a JOIN. The alternative would be:

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);
Community
  • 1
  • 1
StuartLC
  • 104,537
  • 17
  • 209
  • 285
  • Thanks. That seems to be listing all records from assessment_criteria, not just limited to those for scheme_of_work_ID = 17. – ICT Teacher Jan 22 '14 at 15:16
  • Really strange though, it works fine as a query in mysql but as soon as I do it from PHP it takes ages to complete the query. :-S – ICT Teacher Jan 22 '14 at 15:34
  • Just a checklist : You'll need indexes on `a.scheme_of_work_id`, the FK `b.assessment_criteria_id` and `b.student_ID`. Also noted that the id columns are all integral - will save a CPU cycle or 2 by removing the quotes :) – StuartLC Jan 22 '14 at 15:39
  • Yep, I keep on hearing about these index things. I suppose they must be important after all. Will do some more reading. Thanks again. – ICT Teacher Jan 22 '14 at 15:55