SQL count / query assistance - mysql

So I'm learning MySQL and I'm trying to do the following:
For each instructor list his / her name and the number of students he / she mentors.
The relevant part of the schema is:
Person(ID, Name)
Student(StudentID, MentorID)
Instructor(InstructorID)
Both InstructorID and StudentID map to Person.ID, and MentorID maps to InstructorID (Each student has an instructor mentor, and both instructors and students are Persons).
I've tried the following to no avail:
select p.Name, count(select s.StudentID
from Student s
where s.MentorID = i.InstructorID)
from Person p, Instructor i
where p.ID = i.InstructorID;
Also this after reading some things on StackOverflow:
select InstructorDetails.Name, count(Mentees)
from Instructor i
inner join Person as InstructorDetails
on InstructorDetails.ID = i.InstructorID
inner join Student as Mentees
on Mentees.MentorID = i.InstructorID;
Any suggestions?

You lack GROUP BY on your query,
SELECT InstructorDetails.Name, count(*) totalCount
FROM Instructor i
INNER JOIN Person as InstructorDetails
ON InstructorDetails.ID = i.InstructorID
INNER JOIN Student as Mentees
ON Mentees.MentorID = i.InstructorID
GROUP BY InstructorDetails.Name

Related

finding the student and teacher with the most courses in common

I need to find which teacher and student have the most overlapping courses (if any) using a MySQL script. I have built my own DB with the following tables:
Students (id, first name, last name)
Professors (id, first name, last name)
Courses (id, name)
Grades (student id, course id, assignment, grade)
Thought Process:
I need to list the students, teachers and courses:
select distinct students.first_name, professors.first_name, course_name from grades
join students on grades.student_id = students.student_id
join courses on grades.course_id = courses.course_id
join professors on courses.professor_id = professors.professor_id
Now I need to look through the information to find which student is taking multiple courses from the same professor. I just don't know how to implement that in MySQL.
Using your query as a base to start, you can group by student and professor to get the number of common courses.
The below query returns the students and professors that have the most common courses:
with cte as (
select
#I had to alias these column names to avoid a duplicate column name error (Quito)
students.first_name, students.last_name,
professors.first_name, professors.last_name,
count(distinct courses.id) counter
from grades
join students on grades.student_id = students.student_id
join courses on grades.course_id = courses.course_id
join professors on courses.professor_id = professors.professor_id
group by
students.first_name, students.last_name,
professors.first_name, professors.last_name
)
select * from cte
where cte.counter = (
select max(counter) from cte
)

Return all courses a student is taking (Many to Many SQL Database example)

I'm fairly new to MySQL, and trying to understand the many-to-many relationship since these examples can popup in interviews
There are 3 tables, and since a Student can have many courses and a Course can have many students, this is a Many-to-Many relationship right?
The tables are
Student- has student ID, name, date of birth, and department.
Courses- Has ID, Name of course
Student_Courses- Has student_id, course_id
How would I display these 2 questions-
1) Given a studentID, return all the names of the courses the student is taking
2) Return the name of students who is taking X amount of courses or more (Ex. 4 or more courses).
Im trying to write queries on these, but I'm stuck...
In the case of selecting all of the courses for a given student ID you could try the following, which will return one row for each Course a Student is associated with.
select
s.name as StudentName,
c.name as CourseName
from `Student` as s
inner join `Student_Course` as sc on (sc.student_id = s.ID)
inner join `Course` as c on (c.ID = sc.course_id)
where
(s.`ID` = 'given_Student_ID_here')
;
As for selecting a list of the names of Students taking N or more courses, for this you might use an aggregating sub-select as a WHERE clause in which we reference one of the outer tables (i.e. [Student]) so that the result of the aggregation is personalised per Student record:
select
s.name as StudentName
from `Student` as s
where
(
(
select count(*)
from `Student_Course` as sc
inner join `Course` as c on (c.ID = sc.course_id)
where (sc.student_id = s.ID)
) >= 4
)
;
You might also consider an alternative approach to this second problem by using the GROUP BY and HAVING clauses:
select
s.name as StudentName
from `Student` as s
inner join `Student_Course` as sc on (sc.student_id = s.ID)
inner join `Course` as c on (c.ID = sc.course_id)
group by
s.name
having
count(*) >= 4
;

SQL, select from two tables based on a third, which references them

Just starting with SQL and the first all-nighter is already here.
I have three tables:
student (student_id, first_name, last_name)
course (course_id, name)
exam (ref_to_student_id, ref_to_course_id, score)
How do I make a select statement and list out student name, last name and course name, for all cases where achieved exam score was > X ?
This is my best shot:
SELECT last_name FROM student WHERE student_id IN
(SELECT ref_to_student_id FROM exam WHERE score > 50)
UNION ALL
SELECT name FROM course WHERE course_id IN
(SELECT ref_to_course_id FROM exam WHERE score > 50)
It's faulty, because I get:
last_name
last_name
name
name
name
and there's no way of telling exactly which student scored above X on which exam/course.
In my mind, something like this:
SELECT first_name, last_name, name
FROM student, course
WHERE student_id, course_id
IN (SELECT ref_to_student_id, ref_to_course_id FROM exam WHERE score > 50)
would produce something like this:
John Doe Chemistry
Jane Dove English
...
But, it only produces a notification about an error in the syntax.
You can use inner join between tables like this:
SELECT s.first_name AS first_name, s.last_name AS last_name, c.name AS course_name
FROM student s
INNER JOIN exam e ON e.ref_to_student_id = s.student_id
INNER JOIN course ON c.course_id = e.ref_to_course_id
WHERE e.score > 50;
You need to join these tables, not union them:
SELECT last_name, first_name, name, score
FROM student s
JOIN exam e ON s.student_id = e.ref_to_student_id
JOIN course c ON e.red_to_course_id = c.course_id
WHERE score > 50
Friend, try this:
SELECT s.first_name, s.last_name, c.name
FROM exam e
JOIN student s ON s.student_id = e.ref_to_student_id
JOIN course c ON c.course_id = e.ref_to_course_id
WHERE e.score > 50
I hope to help you!

Get all data from a table that contains two foreign key data

Table instructor: ID, name, dept_name, salary
Table student: ID, name, dept_name, tot_cred
Table advisor: s_ID, i_ID which contains student id and instructor id for the two table.
I need to find all the instructor and student's name where the department of the advisor is CComp.Sci
I can find all the id of the instructor and student whrer the intructor is fom Computer science. And only the name of the students.
But can't figure out both the name at the same time.
I wrote this:
SELECT student.name
FROM student
WHERE student.ID in (SELECT advisor.s_ID
FROM advisor
, instructor
WHERE advisor.i_ID = instructor.ID
and instructor.dept_name = 'Comp.Sci')
The root solution I think you need here is just a simple join between the three tables. But since you need a single list of both student and instructor names, this complicates things. One option is to union together a query which finds the matching students along with a query which finds the matching instructors.
SELECT s.name, 'student' AS type
FROM student s
INNER JOIN advisor a
ON s.ID = a.s_ID
INNER JOIN instructor i
ON a.i_ID = i.ID
WHERE i.dept_name = 'CComp.Sci'
UNION ALL
SELECT DISTINCT i.name, 'instructor'
FROM student s
INNER JOIN advisor a
ON s.ID = a.s_ID
INNER JOIN instructor i
ON a.i_ID = i.ID
WHERE i.dept_name = 'CComp.Sci'
Using "where .. in (..)" will give you bad performance, also it will not allow you to get the data from the table in the where clause.
Here is a solution if you mean to get the result of instructor name side alone with student name.
SELECT S.name AS Student,I.name AS Instructor
FROM Students AS S
JOIN Advisor AS A ON A.s_ID = S.Id
JOIN Instructor AS I ON I.Id = A.i_ID
WHERE I.dept_name = 'Comp.Sci'
*notice that I used alias
** if you want for example to get all students even those who lack instructor use LEFT JOIN

Using Count in sql

I need help writing a Sql command. I am pretty new at sql so everything is a little confusing.
The problem:
For each instructor list his / her name and the number of students he / she mentors
There are three tables:
Person with the Names and ID
Instructor with Instructor ID which references ID
Student with StudentID and MentorID which references ID
I tried:
select distinct p.Name,count(d.MentorID)
from Person p, Instructor e, Student d
where e.InstructorID = d.MentorID
and p.ID = e.InstructorID;
But that only gives me one results instead a count per instructor.
Build a group and then count() counts for every group and not the complete result.
select p.Name, count(d.MentorID)
from Person p
join Instructor e on p.ID = e.InstructorID
join Student d on e.InstructorID = d.MentorID
group by p.Name