This sample code her just figures out the grade average for table 3, not the true GPA : SELECT *
FROM (
SELECT AVG(g.Grade) as average_grade, g.SSN
FROM Grade g
group by g.SSN) a
inner join Student s on a.ssn = s.ssn;
Tying to figure out the correct formula: Here is what I have came up with but it is not correct
SELECT *
FROM (
SELECT SUM(Grade*CreditHour)/(SUM(CreditHour) as average_grade, g.SSN
FROM Grade g
group by g.SSN) a
inner join Student s on a.ssn = s.ssn;
Need some help stuck on this problem?
It looks to me as if you simply forgot to join the grade table with the course table. Or am I missing something?
SELECT *
FROM
(
SELECT
SUM(g.Grade*c.CreditHour) / SUM(c.CreditHour) as average_grade,
g.SSN
FROM Grade g
INNER JOIN Course c ON c.cno = g.cno
GROUP BY g.SSN
) a
INNER JOIN Student s ON a.ssn = s.ssn;
Related
I have the following 3 tables for students and I need to find the names of students who currently are enrolled in classes that meet at the same time
student(**snum**, sname, major, level, age)
class(**cname**, meets_at, room)
enroll(**snum**, **cname**)
The keys for each table is in bold.
I have tried the folling code and I'm not sure whether I'm close to the correct answer here.
select s.sname
from student s
join
( select c.cname
, c.meets_at
, (count(*)
from class c
having count( * ) > 1
) e
on c.cname = e.cname
and s.snum = e.snum;
I would think of this as joining on students with meetsat. So, this gets students with their class times:
select s.sname, c.meets_at
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname;
Then, to get the duplicates, use aggregation and filter using having:
select s.snum, s.sname, c.meets_at, count(*) as cnt
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
Note that this includes the ids as well as the name, because two students could have the same name.
Finally, a student could have multiple pairs of classes that conflict, but you only want to see the student once. Although the above is probably sufficient for your purposes, a more accurate solution for the stated problem would be:
select distinct s.sname
from students s join
enrolls e
on s.snum = e.snum join
classes c
on c.cname = e.cname
group by s.snum, sname, c.meets_at
having count(*) >= 2;
select s.snum, s.sname, c.meets_at ,count(*) as cnt into #tempStudents
from students s
join enrolls e on s.snum = e.snum
join classes c on c.cname = e.cname;
Put the whole data in temporary table
select sname from #tempStudents
group by snum,sname ,meets_at
having cnt >=2
Now apply filtration on temporary table for getting desire data
and if u need distinct name of student put Distinct keyword before sname.
I make a query, that show each user answer amount of question for each department and correct and incorrect percent of each user when they answer question for that department.
So, I try a query like this,
SELECT d.department_id, d.department_name as department,
a.username, COUNT(a.username)total,
( (COUNT(r.is_correct)*100) /
( SELECT COUNT(a.username) total
FROM qa_report r
LEFT JOIN tbl_user a ON (r.user_id = a.admin_id)
LEFT JOIN department d on (a.department_id = d.department_id)
WHERE d.department_name = 'Dept1' AND is_correct='yes'
)
) as correct_percent
FROM qa_report r
LEFT JOIN tbl_user a ON (r.user_id = a.admin_id)
LEFT JOIN department d on (a.department_id = d.department_id)
WHERE d.department_name = 'Dept1'
GROUP BY a.username
This is the result,
total column is the amount of question's answer that user answer for that department.
In this total, correct and incorrect answer are mixing.
but the correct_percent column is still wrong when I try to calculate correct/incorrect percent of each department.
The problem is at this line,
( (COUNT(r.is_correct)*100) /
( SELECT COUNT(a.username) total
FROM qa_report r
LEFT JOIN tbl_user a ON (r.user_id = a.admin_id)
LEFT JOIN department d on (a.department_id = d.department_id)
WHERE d.department_name = 'Dept1' AND is_correct='yes'
)
) as correct_percent
I need to get the correct percent of each user at that place like this,
(correct percent of answer*100)/total question that user answer
eg. John => total: 10, correct 5, incorrect 5, correct %=50%
I very appreciate for any suggestion.
I can solve this problem now. I was wrong when I try to calculate percentage.
Here is the query that work,
SELECT d.department_id, d.department_name as department,
a.username, COUNT(a.username)total,
( (COUNT(CASE WHEN r.is_correct='yes' THEN 1 END)*100) / ( COUNT(a.username)) ) as correct_percent,
( (COUNT(CASE WHEN r.is_correct='no' THEN 1 END)*100) / ( COUNT(a.username)) ) as incorrect_percent
FROM qa_report r
LEFT JOIN tbl_user a ON (r.user_id = a.admin_id)
LEFT JOIN department d on (a.department_id = d.department_id)
WHERE d.department_name = 'Dept1'
GROUP BY a.username
Hope this help for someone.
I have a database with the tables:
Student(SID,Name,Surname,Age)
Registration(StudentID,CourseID)
Course(CID,Name,Cost)
I would like to extract only the name of the courses with students younger than 20. Will the query below do just that?
SELECT C.NAME
FROM Course C
INNER JOIN Registration
INNER JOIN Student S
WHERE CID = CourseID
AND SID = StudentID
AND Age < 20
GROUP BY C.NAME
I would also like to extract the number of students in each course having students younger than 20. Is it correct to do it as below?
SELECT count(S.NAME)
,C.NAME
FROM Student S
INNER JOIN Course C
INNER JOIN Registration
WHERE Age < 20
AND CID = CourseID
AND SID = StudentID
GROUP BY C.NAME
You are missing the ON part for the join otherwise it would just be a CROSS JOIN.
Your first query should look like this if you want just a distinct list of student names:
SELECT DISTINCT C.NAME
FROM Course C
INNER JOIN Registration R ON C.CID = R.CourseID
INNER JOIN Student S ON R.StudentID = S.SID
WHERE Age < 20
Your second query shouldn't really have the C.Name in the select if you want to get just a count unless you want a count of how many students have that name.
SELECT count(*)
FROM Student S
INNER JOIN Registration R ON s.SID = R.StudentID
INNER JOIN Course C ON c.CID = R.CourseID
WHERE Age < 20
GROUP BY C.NAME
First join these tables, then group by Course's PK(CID), Add the HAVING condition to filter the course which has students younger than 20.
Then use Course table to join the result to get the course name and count of students in the course.
SELECT
T1.Name,
T2.StudentCount
FROM
Course T1
INNER JOIN (
SELECT
c.CID,
COUNT(s.SID) AS StudentCount
FROM
Course c
LEFT JOIN Registration r ON c.CID = r.CourseID
LEFT JOIN Student s ON s.SID = r.StudentID
GROUP BY c.CID
HAVING COUNT(IF(s.Age < 20, 1, NULL)) > 0
) T2 ON T1.CID = T2.CID
More correctly, you should move the conditions of the join, to the join statements themselves by including them in the on clause instead of the where. While the results may not change in this instance, if you were to start including outer joins you would encounter difficulties.
SELECT count(S.NAME)
,C.NAME
FROM Student S
INNER JOIN Registration R
ON s.SID = R.StudentID
INNER JOIN Course C
ON c.CID = R.CourseID
WHERE Age < 20
GROUP BY C.NAME
There's a fiddle here showing it in action: http://sqlfiddle.com/#!9/c3b8f/1
Your first query will also produce the results you want, but again, you should move the join predicates to the join itself. Also, you don't need to perform the grouping just to get distinct values, mysql has an expression for that called distinct. So rewritten, the first query would look like:
SELECT DISTINCT C.NAME
FROM Student S
INNER JOIN Registration R
ON s.SID = R.StudentID
INNER JOIN Course C
ON c.CID = R.CourseID
WHERE Age < 20.
Again, the results are the same as what you have already but it is easier to 'read' and will put you in good stead when you move on to other queries. As it stands you have mixed implicit and explicit join syntax.
This fiddle demonstrates both queries: http://sqlfiddle.com/#!9/c3b8f/4
edit
I may have misinterpreted your original question - if you want the total number of students enrolled in a course with at least one student under 19, you can use a query like this:
select name, count(*)
from course c
inner join registration r
on c.cid = r.courseid
where exists (
select 1
from course cc
inner join registration r
on cc.cid = r.courseid
inner join student s
on s.sid = r.studentid
where cc.cid = c.cid
group by cc.cid
having min(s.age) < 20
)
group by name;
Again with the updated fiddle here: http://sqlfiddle.com/#!9/c3b8f/17
My database contains students and marks tables, which you can see visiting http://www.sqlfiddle.com/#!2/817367/1. Query should return all studends whose got all marks which has gotten student 'c' (1, 2, 3), that is - b, e, f.
I have solved problem partly getting all students.name which has any of marks.score where students.name = 'c', but I can't figure out how to force to check all marks.score-es of 'c'.
...Hopefully question is clear.
Thanks in advance.
the other solutions are good for this time, but if you want a solution without using aggregate functions like "COUNT" then consider this.
http://www.sqlfiddle.com/#!2/817367/39
SELECT `name`
FROM students
JOIN (SELECT DISTINCT s_id
FROM marks AS marks1
WHERE marks1.`s_id` NOT IN(
SELECT DISTINCT marks2.s_id
FROM (SELECT score
FROM marks
JOIN students ON marks.`s_id` = students.`id`
AND students.`name` = 'c') AS c_scores
CROSS JOIN marks AS marks2
ON marks2.`s_id` NOT IN (
SELECT s_id
FROM marks
JOIN students ON marks.`s_id` = students.`id`
AND students.`name` = 'c')
LEFT JOIN marks AS marks3 ON marks3.`s_id` = marks2.s_id
AND marks3.`score` = c_scores.score
WHERE marks3.`s_id` IS NULL
)) AS good_ids
ON students.`id` = good_ids.s_id
WHERE `name` != 'c'
Another similiar solution:
SELECT s2.name
FROM marks m1
JOIN marks m2 ON m2.score = m1.score
JOIN students s1 ON s1.id = m1.s_id
JOIN students s2 ON s2.id = m2.s_id
WHERE s1.name = 'c' AND s2.name != 'c'
GROUP BY s2.id
HAVING COUNT(DISTINCT m1.score)
= (SELECT COUNT(DISTINCT m.score)
FROM marks m
JOIN students s ON s.id = m.s_id
WHERE s.name = 'c')
got it ...phew, your requirements are weird as hell haha but this should give you what you need with a single input 'c'
maybe there are room to improve but at this point you're on your own.
somehow i can't update the fiddle so here it is
select t1.name
from
(select s1.name,count(*) as count
from marks m1
inner join marks m2 using (score)
inner join students s1 on (s1.id=m2.s_id)
inner join students s2 on (m1.s_id=s2.id)
where s2.name='c'
group by m2.s_id
) as t1
JOIN
(select count(*) as min_count
from marks m
inner join students s on (m.s_id=s.id)
where s.name='c'
) as t2
where
t1.name != 'c'
and t1.count >= t2.min_count
I am having trouble trying to create a query to:
Select all the students who have not completed all peer review's for a particular week.
background: Each week, every student must peer review their peers in the same group.
Each group can be a different size, which is the problem I am having.
this is my current test data:
Table 1: peer review table
Table 2: student table.
This is my inital query, groups all the students based on the amount of peer review's they've made. I now need to to check if the count(*) is less than the size of the group for each student :
SELECT *
FROM peerreview
RIGHT JOIN student
ON student. studentID = peerreview.reviewer
WHERE week = 11
GROUP BY studentID
HAVING Count(*) < ????
Following query will return the student which has reviewed all the students in same group.
SELECT a.reviewer,
a.groupid
FROM (SELECT student2.studentID AS reviewer,
student1.groupid,
Count(*) AS cnt
FROM student student1
INNER JOIN peerreview
ON student1.studentID = peerreview.reviewee
INNER JOIN STUDENT STUDENT2
ON student2.studentID = peerreview.reviewer
WHERE student2.groupid = student2.groupid
AND peerreview.week = 11
GROUP BY student1.groupid,
student2.studentID) a
INNER JOIN (SELECT groupid,
Count(*) - 1 AS cnt
FROM student
GROUP BY groupid) b
ON a.groupid = b.groupid
AND a.cnt = b.cnt
See SqlFiddle
Select S.StudentId As Reviewer
, S1.StudentId As StudentYetToBeReviewed
, Weeks.WeekNum
From Student As S
Join Student As S1
On S1.GroupId = S.GroupId
And S1.StudentId <> S.StudentId
Cross Join (
Select 7 As WeekNum
Union All Select 11
) As Weeks
Where Not Exists (
Select 1
From PeerReview As P1
Where P1.reviewee = S1.StudentId
And P1.Week = Weeks.WeekNum
)
Order By WeekNum, reviewer
This provides you a list, by week, of the reviewer and the person they need to review. In the real solution, you would want to replace the Cross Join of weeks with a distinct list of weeks in which reviews should happen.
SQL Fiddle version
select distinct s1.*
from student s1 inner join student s2 on s1.groupId = s2.groupeId
left join peerreview pr on pr.revieweer = s1.studentId
and pr.reviewee = s2.studentId
where pr.Week = ? and pr.revieweer is null and s1.studentId <> s2.studentId