Asking a simple question, just want everyone have fun to solve it.
I got 2 tables.
1. Student
2. Course
Student
+----+--------+
| id | name |
+----+--------+
| 1 | User1 |
| 2 | User2 |
+----+--------+
Course
+----+------------+------------+
| id | student_id | course_name|
+----+------------+------------+
| 1 | 1 | English |
| 2 | 1 | Chinese |
| 3 | 2 | English |
| 4 | 2 | Japanese |
+----+------------+------------+
I would like to get the result all student, who have taken English and Chinese, NOT English or Chinese.
Expected result:
+----+------------+------------+
| id | student_id | course_name|
+----+------------+------------+
| 1 | 1 | English |
| 2 | 1 | Chinese |
+----+------------+------------+
What we normally do is
select * from student join course on (student.id = course.student_id) WHERE course_name = 'English' OR course_name = 'Chinese'
but in this result I can get User2 record which is not my expected result. I want the record only display the User take the course English+Chinese only.
Just join onto course twice: once for English, once for Chinese. That is:
or even
which will also eliminate duplicate (student_id,course_name) entries from course.
I’m assuming (student_id,course_name) is indexed to drive both these. Your naming is a bit odd: the “course” table doesn’t describe a course, it describes the association from a student to a course. Personally, I’d call it “student_course” (or similar, maybe suffix “_map” or “_link”) and have it contain a “course_id” referencing a course table with an id and name.
(I also prefer to have primary keys named consistently rather than calling them “id” in their own table, but that’s just being picky, and much more subjective)
Just for fun:
The reality is that using “intersect” to compare two result sets based on the same tables is a bit silly.