I have a Students table and a Courses table. They have a many to many relationship between them and the StudentCourses table is the intermediary. Now, I have a list of Course ids and want to select the Students that follow all Courses in my list. How??
--CREATE TYPE CourseListType AS TABLE --( -- CourseID INT --) DECLARE @CourseList CourseListType CREATE TABLE #Students ( ID INT ,Name CHAR(10) ) CREATE TABLE #Courses ( ID INT ,Name CHAR(10) ) CREATE TABLE #StudentCourses ( StudentID INT ,CourseID INT ) INSERT INTO @CourseList (CourseID) VALUES (1) --English ,(2) --Math INSERT INTO #Students (ID, Name) VALUES (1, 'John') ,(2, 'Jane') ,(3, 'Donald') INSERT INTO #Courses (ID, Name) VALUES (1, 'English') ,(2, 'Math') ,(3, 'Geography') INSERT INTO #StudentCourses (StudentID, CourseID) VALUES (1, 1) ,(1, 2) ,(2, 1) ,(2, 2) ,(3, 1) ,(3, 3)
In this example, I only want the result to be John and Jane, because they both have the two courses in my CourseList. I dont want Donald, because he only has one of them.
Have tried this JOIN, construction, but it does not eliminate students that only have some of my desired courses.
SELECT * FROM @CourseList CRL INNER JOIN #Courses CRS ON CRS.ID = CRL.CourseID INNER JOIN #StudentCourses STC ON STC.CourseID = CRS.ID INNER JOIN #Students STD ON STD.ID = STC.StudentID
Advertisement
Answer
If you want students with all your required courses, you can use aggregation and having
:
SELECT sc.StudentId FROM #StudentCourses sc JOIN @CourseList cl ON sc.CourseID = cl.id GROUP BY sc.StudentId HAVING COUNT(DISTINCT sc.CourseId) = (SELECT COUNT(*) FROM @DcourseList);
If you want additional information about students, you can join in the Students
table (or use a IN
or a similar construct).
Note that this only needs the StudentCourses
table. It has the matching ids. There is no need to join in the reference tables.