SQL Am I using this join correctly? - mysql

Using a university relation (students are advised by instructors in different departments, only one advisor per student but advisors can have zero to many advisees), I'm attempting to write a function that computes the total number of students being advised in a given department.
Here are the tables and columns for reference:
student(id,name,dept_name,tot_cred)
instructor(id,name,dept_name, salary)
advisor(s_id,i_id)
I already know how to use delimiter and such so no I don't need to be told how to write a function. I'm just having issues getting what I want from the select statement alone.
This is the best I've been able to come up with so far:
SELECT *
FROM advisor
RIGHT OUTER JOIN instructor
ON i_id=id
ORDER BY dept_name;
This statement yields:
Is there a way I can write an if statement or some other statement to delete all of the NULL entries and then use a count function (within the custom function I'll be writing) that will count the number of instances dept_name occurs, resulting in the total number of advisees per department?

SELECT i.dept_name, COUNT(a.s_id)
FROM Instructor i
LEFT JOIN advisor a ON i.id = a.i_id
GROUP BY i.dept_name;
This will include zeros for departments with no advisees.

If you are interested in the number of advised students per student department then:
SELECT s.dept_name, COUNT(a.s_id)
FROM student s
LEFT JOIN advisor a ON a.s_id=s.id
GROUP BY s.dept_name
OTOH, if you are interested in the number of advised students per instructor department then:
SELECT i.dept_name, COUNT(a.s_id)
FROM instructor i
LEFT JOIN advisor a ON a.i_id=i.id
GROUP BY i.dept_name

It looks like this is what you need:
SELECT i.dept_name, COUNT(a.s_id) FROM instructor i
LEFT OUTER JOIN advisor a ON i.id = a.i_id
GROUP BY i.dept_name;
I have to add that advisor(s_id,i_id) is bad database design if a student really can not have more than 1 advisor as you said. Because in that case, simply add advisor_id to the student relation and get rid of the advisor table.
Also: your use of the word 'function' is incorrect. We are talking about queries here.

Probably you can try this:
SELECT i.dept_name, COUNT(s.*) AS totalAdvisedNum
FROM student s, advisor a, instructor i
WHERE a.s_id = s.id AND a.i_id = i.id GROUP BY i.dept_name
This will select the department name and total number of students being advised by instructors in these departments
If you need to get the number for a specific department you should replace GROUP BY i.dept_name with AND i.dept_name = "name of department"

Related

Having trouble a query and specifically with joins

The code below is completely wrong and does not work at all. Im basically trying to look through my tables and compile a list of DeptName and the total student number for a department where a department has more than 40 students.
Im confused about joins in general and if someone could explain and show where im going wrong. im sure there is also other problems so any help with them would help
So basically one department is connected to one module, and a student is enrolled in a module. A student cannot take a module outside of their department. So each student should have one module that connects to one department
All of the ID fields in other tables are foreign keys as you can guess and changing the tables is not what I want to do here I just want to do this query as this stands
Relevant tables columns
Table Department DeptID, DeptName, Faculty, Address
Table Modules ModuleID, ModuleName, DeptID, Programme
Table Students StudentID,StudentName,DoB,Address,StudyType,`
Table Enrolments EID,StudentID,ModuleID,Semester,Year
SELECT Department.DeptName, COUNT(Student.StudentID) AS 'No of Students' FROM Department LEFT JOIN Module ON Department.DeptID= Module.DeptID LEFT JOIN Enrolment ON Module.ModuleID= Enrolment.StudentID LEFT JOIN Student.StudentID
GROUP BY(Department.DeptID)
HAVING COUNT(Student.StudentID)>=40
I have not included every table here as there are quite a lot.
But unless i've got this completely wrong you don't need to access a ModuleID in a staff table for the module they teach or something not relevant to this at all. As no student or Dept details are in there.
If that is the case i will fix it very quickly.
SELECT Department.DeptName, COUNT(Student.StudentID) AS 'No of Students'
FROM Department
LEFT JOIN Module
ON Department.DeptID= Module.DeptID
LEFT JOIN Enrolment
-- problem #1:
ON Module.ModuleID= Enrolment.StudentID
-- problem #2:
LEFT JOIN Student.StudentID
-- problem #3:
GROUP BY(Department.DeptID)
HAVING COUNT(Student.StudentID)>=40
You're joining these two tables using the wrong field. Generally when the modeling is done correctly, you should use USING instead of ON for joins
The right side of any JOIN operator has to be a table, not a column.
You have to group by every column in the select clause that is not part of an aggregate function like COUNT. I recommend that you select the DeptID instead of the name, then use the result of this query to look up the name in a subsequent select.
Note : Following code is untested.
WITH bigDepts AS (
SELECT DeptId, COUNT(StudentID) AS StudentCount
FROM Department
JOIN Module
USING ( DeptID )
JOIN Enrolment
USING ( ModuleID )
JOIN Student
USING ( StudentID )
GROUP BY DeptID
HAVING COUNT(StudentID)>=40
)
SELECT DeptID, DeptName, StudentCount
FROM Department
JOIN bigDepts
USING ( DeptID )
Instead of left join you need to use inner join since you need to select related rows only from those three tables.
Groupy by and having clause seems fine. Since you need departments with more than 40 students instead of >= please use COUNT(e.StudentID)>40
SELECT d.DeptName, COUNT(e.StudentID) AS 'No of Students' FROM Department d INNER JOIN Module m ON d.DeptID= m.DeptID inner JOIN Enrolment e ON m.ModuleID= e.StudentID LEFT JOIN Student.StudentID
GROUP BY(d.DeptName)
HAVING COUNT(e.StudentID)>40
So your join clause was a bit iffy to students as you wrote it, and presumably these should all be inner joins.
I've reformatted your query using aliases to make it easier to read.
Since you're counting the number of rows per DeptName you can simply do count(*), likewise in your having you are after counts greater than 40 only. Without seeing your schemas and data it's not possible to know if you might have duplicate Students, if that's the case and you want distinct students count can amend to count(distinct s.studentId)
select d.DeptName, Count(*) as 'No of Students'
from Department d
join Module m on m.DeptId=d.DeptId
join Enrolment e on e.StudentId=m.ModuleId
join Students s on s.StudentId=e.studentId
group by(d.DeptName)
having Count(*)>40
Also, looking at your join conditions, is the Enrolement table relevant?
select d.DeptName, Count(*) as 'No of Students'
from Department d
join Module m on m.DeptId=d.DeptId
join Students s on s.StudentId=m.moduleId
group by(d.DeptName)
having Count(*)>40

Selecting the same row between 2 tables relative to the ID

I am a beginner with SQL syntax. I have 2 tables called STUDENT and EXAMINATION and I am, in 1 line, trying to write a query to print ID, SUBJECT and NUMBER_OF_TIMES. I am not told which column belongs to which table but my guess is that ID belongs to STUDENT and SUBJECT belongs to EXAMINATION. NUMBER_OF_TIMES is just how many times the same student has taken that subject exam.
I tried SELECT STUDENT.ID, EXAMINATION.SUBJECT, NUMBER_OF_TIMES but no luck.
Your working query would look something like this:
SELECT
s.ID,
e.SUBJECT,
COUNT(e.STUDENT_ID) AS cnt
FROM STUDENT s
LEFT JOIN EXAMINATION e
ON s.ID = e.STUDENT_ID
GROUP BY
s.ID,
e.SUBJECT
This answer assumes, really out of necessity, that there exists a join column STUDENT_ID in the exam table, which connects with the student table. We use a left join so as to report all students, even those with a zero count.

Need to display records by joining two tables and the records should be Unique

I have the two tables STUDENT and TaskEffort.
Many students have worked on same tasks. For a particular task the name of the students and effort should be considered.
The STUDENT table contains studentid, firstName and lastName.
The TaskEffort table contains taskid, studentid and Effort
I need to display the taskid, first name, last name, effort, for those who worked on a particular task.
This is one of the queries I tried, but this is not working.
SELECT t.id, s.firstname, s.lastname, t.effort
FROM taskeffort t
LEFT OUTER JOIN student s ON t.id = 4 AND s.studentid = t.studentid
Thanks in advance.
First the design is not accurate.
You said that "Many students must have worked on same task" but your design is
1-many students. It means that each task has only one student. You need to change the design to support you requirements.
this relation is many-to-many. Student can be assigned to many tasks and tasks may have been assigned to many students.
Add a third table called taskAssignments with columns: student_id,task_id and remove student_id column from TaskEffort.
Then run this query:
SELECT t.id, s.firstname, s.lastname, t.effort
FROM TaskEffort t
LEFT JOIN taskAssignments ta ON t.id=ta.task_id
LEFT JOIN student s ON s.studentid = ta.studentid
WHERE t.id = 4
SELECT t.id, s.firstname,s.lastname, t.effort
FROM taskeffort t
LEFT OUTER JOIN student s ON s.studentid = t.studentid
WHERE t.id = 4;

How to return all rows that exists in each group?

EDIT:
This is the database. The question is:
Find the course title which all the students whom their advisor is professor Katz took that course.
What I thought to solve this question:
1) Find ID of Prof. Katz.
2) Using that ID, find IDs of students whom Prof. Katz advises.
3) Using the founded student IDs, find all courses where Prof. Katz's advisees took.
4) Group the result by student IDs and get the rows present in each group, hence finding the course taken by all advisees of Prof. Katz.
I couldn't perform the step 4.
How to return all rows from a grouped table, where each returned row exists in every group of the table?
SELECT Title
FROM Course INNER JOIN Takes
ON Course.Course_ID = Takes.Course_ID
WHERE Takes.ID IN
(SELECT Student.Id
FROM Student INNER JOIN advisor ON Students.ID = Advisor.s_ID
INNER JOIN instructor ON Advisor.i_ID = Instructor.ID
WHERE Instructor.Name = 'Prof.Katz' )

MySQL Query: How to join and group and I don't know what they're called

I'm relatively new to MySQL and have tried to teach myself how to use it so sorry if I'm not using the right terminology...
I have 2 tables: Students and Payments
The Payments table has a Student ID, Amount and Type (either Bond, Installment or Repair)
I am having trouble trying to figure out how to get a column for the sum of all bond payments and another for the sum of all instalment payments for each student and showing all the students that have a payment or not.
Alternatively, if you know any good guides for free (my budget is $0) that can help, that would be appreciated.
Thanks
Since you want all students, even if they don't have any matches in payments, you must use a LEFT JOIN.
select students.*, payments.type, SUM(payments.amount)
from students
left join payments on payments.student_id = students.id
group by students.id, payments.type
Note that this puts the different payment types each on their own row. Turning them into columns in the result is called pivoting. Some database systems have built-in ways to do this, but MySQL doesn't. Doing it requires knowing all the possible values of payments.type.
select students.*,
SUM(IF(payments.type = 'Bond', payments.amount, 0)) Bond,
SUM(IF(payments.type = 'Installment', payments.amount, 0)) Installment,
SUM(IF(payments.type = 'Repair', payments.amount, 0)) Repair
from students
left join payments on payments.student_id = students.id
group by students.id
I am suggesting you the query how you can get sum of all bond payments and installment payments.
Select student_id , sum(amount),Type from payments group by student_id,Type
To learn about the Mysql please refer the following sites.
http://www.tutorialspoint.com/mysql/
http://www.w3schools.com/sql/
http://www.mysqltutorial.org/