I'm struggling writing a query in Entity Framework that deals with a many to many relationship that I have set up. What I want to do is get the items from TableA that belong to a relationship with TableB and at the same time know from the results which relationship was a correct match.
For instance, if I'm using Students and Courses, I want to look for all the students that are in a set of courses and also return only those courses that matched. I very specifically want to start the query with Students, as this can easily be accomplished by just looking at the Courses navigation property to get the list of students.
What I want is a list of Students where each Student contains only the set of Courses in my query (NOT every course the student is taking).
Something like the below is close, I get the correct list of Students, but the navigation property for Courses shows all Courses, not the subset from my query. I want to avoid having to query again if possible, and just return the set of Students / Courses I need.
Dim listOfStudents = From s In Students
From c In s.Courses
Where listOfCourseIds.Contains(c.CourseId)
If there's no junction table between the two, then try:
from s in dc.Students
from c in s.Courses
where c.CourseID == courseID
select s;
If entity has a junction table between the two, try:
from s in dc.Students
from e in s.StudentsCourses
where e.Course.CourseID == courseID
select s;
Related
I'm working on my SQL project using the Oracle database for class, and I'm asked a question that I see far too often.
You have three tables:
STUDENT: SNO, SNAME
CLASS: CNO, CNAME
ATTENDANCE: SNO, CNO, Grade
The question I keep finding is of a similar type: Find the names of the students that attend in all of the classes that "John" (or anyone else) attends.
John attends three classes, so I have to find the students that also attend those three classes (could be more, but those three must be there). However, I won't always know how many classes John (or whoever) attends, so it can't be hardcoded like that.
SELECT jclass.CNO
FROM attendance jclass
INNER JOIN student on jclass.SNO = student.SNO
WHERE student.SNAME = 'John';
This gets me the classes that John attends. I tried to add the identifier for the other students:
SELECT student.SNAME
FROM student
INNER JOIN attendance on student.SNO = attendance.SNO
INNER JOIN class on attendance.CNO = class.CNO
WHERE student.SNAME <> 'John'
AND class.CNO IN (SELECT jclass.CNO
FROM attendance jclass
INNER JOIN student on jclass.SNO = student.SNO
WHERE student.SNAME = 'John');
However, this only gets me the students that appear in at least one of John's classes, rather than all of them. I can see why it's doing this, but I'm not sure how to fix it. It's the one big struggle I'm having with SQL.
Here is one way - assuming SNO is primary key in the first table, CNO is primary key in the second table, and (SNO, CNO) is (composite) primary key in the third table, and that the input student is given by a unique identifier (first name is distinctly NOT a unique identifier, so the problem stated in terms of giving "John" as the input makes no sense). Here I assume the "special" student is identified by SNO = 1001; you can make 1001 into a variable, or change it to a subquery that selects a (unique!!) SNO based on some other inputs.
I didn't try to make the query as efficient as possible, or use features you most likely haven't seen in your class. Rather, I tried to make it as elementary and as readable as possible.
select sno
from attendance
where cno in (select cno from attendance where sno = 1001)
group by sno
having count(*) = (select count(*) from attendance where sno = 1001)
;
The strategy is simple: the subquery in the in condition finds the classes attended by the "special" student, then from the attendance table we select only rows for those classes. Group by student, and count. Keep only the students for whom the count is equal to the total count for the "special" student. Note the last condition is about groups, not about input rows, so it belongs in the having clause.
I'm sorry for the weird title, I didn't know how to summarize my question. If you have a better idea, let me know and I'll update it.
Suppose I have a database scheme containing table fro both students and classes. I also have a third table connecting the first two, so I know which student attends which classes. This third connection table only contains two foreign keys, the student id and the class id.
I know how get a list of all classes attended by a single student or hot to get all students in a single class.
My question, however, is, how do I get all the students who attend ALL of the classes A, B, C and D and not just one of them?
Thanks in advance.
You can use aggregation:
select student_id
from student_classes sc
where class_id in (A, B, C, D)
group by student_id
having count(*) = 4;
I am creating an app that makes guest lists for greek life events at universities.
The two tables I am working with are 'student' table and 'participant' table.
The fields in the student table are: student_id, student_name, university, and chapter.
Students with chapter id's are considered members, and students without chapter id's are considered guests when making guest lists(participant table).
The participant table fields are: participant_id, member(which is related to student_id), guest (which is also related to student_id), and event.
When trying to add guests to the guest list for an event, I wrote the following sql query to filter out students from different universities and that aren't in chapters and weren't already on the list:
$student = getColumn("SELECT guest FROM participant WHERE event = '$event'");
$university = getSqlValue("SELECT university FROM student WHERE student_id = '$member'");
$f->setOption('filter',
"SELECT student_name
FROM `student`
LEFT JOIN participant ON student.student_id = participant.guest
WHERE student.chapter = ''
AND student.university = '$university'
AND participant.guest != '$student'");
So, I know this isn't going to work, because I have a whole array for $student, but even if I try it with one student id, the query doesn't work. It returns empty. If I remove the last AND particpant.guest!= $student, then the query returns all the students at the university that are not members of a chapter.
My question has two parts:
Why wouldn't that query work with one value for student?
Can someone think of a better way to go about doing this?
Which SQL query could I write to satisfiy this need:
"List the names of the students who take a course from instructor named John."
Not sure that you can, from the depicted relations.
You can identify tutors by selecting on InstructorID and filtering on Instructor.FirstName.
You can join that subset onto course, via the InstructorCourses Join Table - join InstructorID to that and join the result to Courses using CourseID
In this way, Instructor.InstructorID -> (InstructorCourses.InstructorID , InstructorCourses.CourseID ) -> Courses.CourseID.
This lets you find information about the courses taught by instructors filtered on their name.
You don't present any link between students and courses in your diagram. I suspect you're missing a relation StudentCourses, which ought to be similar to InstructorCourses, but rather links students to courses. With that data in the mix, you can extend the join to match students to the courses from the relationship you already have.
Your diagram implies a relation between Student and InstructorCourses, which seems incorrect - both because there is no key to join on, and also because the logical relationship would not be correct. I think this is probably an error.
It is impossible to satisfy the SQL query you need because your conception does not allow it in that there is no relationship between the 2 tables Student and InstructorCourses.
I’ve been hours trying to build this query and I need your help so I can make it.
This is table Students (made out of inner joins):
SpecialtyChosenID StudentID Subject SubjectSpecialtyID
5ABFB416-8137 15 Math A1EBF3CB-E899
5ABFB416-8137 15 English A1EBF3CB-E899
The info in it means that a student with id no. 15 has chosen an specialty with id 5ABFB416-8137
The two subjects he has passed (Math and English) belong to a specialty with id A1EBF3CB-E899
What would be the query to know if the passed subjects belong to the specialty chosen by the student??
Counting the number of subjects with the same SubjectSpecialtyID as SpecialtyChosenID and vice versa could do.
Thanks a lot
You can do a self join. This finds the number of subjects taken by the student that match the student's chosen specialities.
SELECT l.SpecialtyChosenID, l.StudentID, Count(Distinct r.Subject) FROM Students l
LEFT JOIN Students r ON (l.StudentID=r.StudentID AND l.SpecialityChosenID=r.SubjectSpecialityID)
GROUP BY l.SpecialtyChosenID, l.StudentID
However, this is quite inefficient using the table structure given. If you have a table listing students with their specialities, and another with subjects and specialities, and a third relating students with subjects, it would be better to build this query from the base data, rather than from the derived data.
SELECT * FROM Students WHERE SpecialtyChosenID = SubjectSpecialtyID
If you only need the list of matching subjects and you have the SpecialtyChosenID you can do something like
SELECT * FROM Students
WHERE SubjectSpecialtyID = SpecialityChosenID
CASE WHEN SpecialtyChosenID = SubjectSpecialtyID THEN 1 ELSE 0 END AS specialty