A Query of certain students in a certain room - sql

I'm working through a problem, working with SQL Oracle. For some reason I am getting the result of 13 for instructors teaching that course when I should only be getting 1. There is only 1 Instructor that teaches only 3 or more students in that room.
Question:
Create a query to determine the number of instructors who have taught more than 3 students in a course section taught in Room L211.
My Code:
SELECT COUNT(Instructor_Id) AS NumberOfInstructors
FROM Section s, Enrollment e
WHERE s.Section_Id = e.Section_Id
AND Location = 'L211'
HAVING COUNT(Student_Id) =
(SELECT COUNT(Student_iD)
FROM Section s, Enrollment e
WHERE s.Section_Id = e.Section_Id
AND Location = 'L211')
ORDER BY s.Course_No;
My Results:
NUMBEROFINSTRUCTORS
-------------------
13
Expected Results:
NUMBEROFINSTRUCTORS
-------------------
1
So I feel like Im kind of going in the right direction maybe not but I feel like it is adding all the instructors up that teach in that class. Ive messed around a lot with that code I've given so if anyone can point me in the right direction. I'm guessing I need to have a count for counting the students who have been in a class with that room number I think I've tried that and got a result of 4 so I'm not sure.
Any help would be great, also here is the Schema.
DBMS: I'm using Oracle SQL Developer

try this:
SELECT COUNT(*) NumberOfInstructors
From (Select Instructor_Id
FROM Section s
join Enrollment e
on e.Section_Id = s.Section_Id
WHERE s.Location = 'L211'
Group By Instructor_Id
HAVING COUNT(Student_Id) >= 3) Z

I think you are needing a subquery here. In pseudo code, you are looking for a query like:
SELECT count(teachers)
FROM
(SELECT count(students) FROM enrollment where location='L211') AS "numberofstudents"
WHERE numberofstudents > 3

I did not test the code, but it seems to me you are missing a condition. Your question requires you to find "Instructor that teaches only 3 or more students in that room", but you did not have any condition to check for student number > 3. Try this:
SELECT COUNT(Instructor_Id) AS NumberOfInstructors
FROM Section s, Enrollment e
WHERE s.Section_Id = e.Section_Id
AND Location = 'L211'
HAVING COUNT(Student_Id) =
(SELECT COUNT(Student_iD)
FROM Section s, Enrollment e
WHERE s.Section_Id = e.Section_Id
AND Location = 'L211' AND COUNT(Student_Id) > 3)
ORDER BY s.Course_No;

Related

Row that should have a 0 count not showing

I'm working through a problem, working with SQL Oracle. I'm getting the right results beside a row that should be showing up that has a count of 0. The question is
Question:
For each section of the Project Management course, list the section ID, location and number of students enrolled. Sort by section ID.
My Code:
SELECT s.Section_Id, s.Location, COUNT(*) AS Enrolled
FROM Course c, Section s, Enrollment e
WHERE c.Course_No = s.Course_No
AND s.Section_Id = e.Section_Id
AND c.Description = 'Project Management'
GROUP BY c.Course_No, s.Location, s.Section_Id
ORDER BY s.Section_Id;
My Results:
SECTION_ID LOCATION ENROLLED
---------- ------------------- ----------
48 L211 4
119 L211 3
120 L214 2
Expected Results:
SECTION_ID LOCATION ENROLLED
---------- ------------------- ----------
48 L211 4
119 L211 3
120 L214 2
121 L507 0
So as you can see I'm missing the row with 0 enrolled on my results and can't seem to get that row to appear. Also you will notice that it is a section id and location that go with it for that project management class but it won't appear. I'm not sure what I'm doing wrong.
Any help would be great, also here is the Schema.
DBMS: I'm using Oracle SQL Developer
How about joining to the tables instead of using the WHERE clause:
SELECT s.Section_Id,
s.Location,
COUNT(e.Section_Id) AS Enrolled
FROM course c
LEFT JOIN section s
ON c.Course_No = s.Course_No
LEFT JOIN enrollment e
ON s.Section_Id = e.Section_Id
WHERE c.Description = 'Project Management'
GROUP BY c.Course_No,
s.Location,
s.Section_Id
ORDER BY s.Section_Id;
#OmniSquad you could use SQL provided by Linger to create LEFT OUTER JOIN and select records where is no enrolment and changes statement COUNT(e.Section_Id) AS Enrolled.
You need to outer join to course and enrollment otherwise you won't see sections that don't have any courses/enrollments. You can either use the ANSI syntax ...LEFT JOIN... etc or the old Oracle syntax using (+) against the columns of the deficient table:-
SELECT s.Section_Id, s.Location, COUNT(*) AS Enrolled
FROM Course c, Section s, Enrollment e
WHERE c.Course_No (+) = s.Course_No
AND s.Section_Id = e.Section_Id (+)
AND c.Description (+) = 'Project Management'
GROUP BY c.Course_No, s.Location, s.Section_Id
ORDER BY s.Section_Id;
These days I would use the ANSI syntax...

SQL query get course number for certain student grades

I'm working through some problems and I can't seem to get the expected results for this one. The question is below with what is in my code right now and also the expected results. If anyone help that would be great. I'm just trying to get a understanding on this and can't seem to get my head around what exactly this is asking as you can see my code I have now isn't close to what the expected result is as of right now. Also I added the schema this will show whats in what table if needed for your guys help.
Question:
List the course number of courses wherein students have received grades for every one of the possible defined grade types. Order by course number.
My code so far:
SELECT g.Student_id, g.Grade_type_code
FROM Grade g LEFT OUTER JOIN Section s
ON g.Section_id = s.Section_id
GROUP BY g.Student_id, g.Grade_type_code
ORDER BY g.Student_id;
Any help would be great, also here is the Schema.
DBMS: I'm using Oracle SQL Developer
Here is the Expected Result
COURSE_NO
----------
20
25
100
120
122
125
130
135
Note: The Chapter for this problem is based off using
LEFT OUTER JOIN
My Current results
STUDENT_ID GRADE_TYPE_CODE
---------- ---------------
102 FI
102 HM
102 MT
102 PA
102 QZ
103 FI
103 HM
103 MT
103 PA
103 QZ
104 FI
104 HM
Based on your ER diagram I believe this query should return a list of courses whose enrolled students have collectively received all of the grade types listed in the GRADE_TYPE table.
select s.course_no,
c.descr,
count(distinct g.grade_type_code) as num_grade_types
from grade g
join enrollment e
on g.student_id = e.student_id
and g.section_id = e.section_id
join section s
on e.section_id = s.section_id
join course c
on s.course_no = c.course_no
group by s.course_no, c.descr
having count(distinct g.grade_type_code) = (select count(grade_type_code)
from grade_type)
I didn't notice your expected result was only the course # (you can just get rid of the columns you don't want from the select list). Also the join to the COURSE table is only there to get the course description, so if you don't want the course description selected, you do not need that join.
You need to select COURSE_NO instead. And also use JOIN and not LEFT JOUTER JOIN.
Something like this:
select COURSE_NO from
(
SELECT distinct (s.COURSE_NO)
FROM Grade g JOIN Section s
ON g.Section_id = s.Section_id
)
ORDER BY s.COURSE_NO;

sub query - list those that have the most

I am trying to list the instructor of the Java courses that have been taught by the Instructor which has taught the most Java courses.
first I select Instructors that teach java courses
SELECT z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO, MAX(b.DESCRIPTION) AS DESCRIPTION
FROM INSTRUCTOR z
JOIN SECTION w ON z.INSTRUCTOR_ID = w.INSTRUCTOR_ID
JOIN COURSE b ON w.COURSE_NO = b.COURSE_NO
WHERE DESCRIPTION like '%Java%'
GROUP BY z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO
it displays results what I want so far
FIRST_NAME LAST_NAME COURSE_NO DESCRIPTION
------------------------- ------------------------- ---------- ---------------------------------
Tom Wojick 120 Intro to Java Programming
Gary Pertez 120 Intro to Java Programming
Anita Morris 124 Advanced Java Programming
Todd Smythe 122 Intermediate Java Programming
Charles Lowry 122 Intermediate Java Programming
Charles Lowry 120 Intro to Java Programming
Fernand Hanks 122 Intermediate Java Programming
etc...
but when I try to select the instructors which has taught the most Java courses I get totally different result
SELECT z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO,b.DESCRIPTION
FROM INSTRUCTOR z
JOIN SECTION w ON z.INSTRUCTOR_ID = w.INSTRUCTOR_ID
JOIN COURSE b ON w.COURSE_NO = b.COURSE_NO
WHERE DESCRIPTION like '%Java%'
GROUP BY z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO,b.DESCRIPTION
HAVING MAX(b.DESCRIPTION) =
(SELECT MAX(DESCRIPTION)
FROM (
SELECT z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO, MAX(b.DESCRIPTION) AS DESCRIPTION
FROM INSTRUCTOR z
JOIN SECTION w ON z.INSTRUCTOR_ID = w.INSTRUCTOR_ID
JOIN COURSE b ON w.COURSE_NO = b.COURSE_NO
WHERE DESCRIPTION like '%Java%'
GROUP BY z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO
)
)
ORDER BY z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO,b.DESCRIPTION;
How could I count these description java courses and select max from it so it can only show one instructor with all his Java courses ?
Perhaps something like:
WITH q AS (
SELECT z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO, MAX(b.DESCRIPTION) AS DESCRIPTION
, COUNT(*) OVER (PARTITION BY z.FIRST_NAME, z.LAST_NAME) TheCount
FROM INSTRUCTOR z
JOIN SECTION w ON z.INSTRUCTOR_ID = w.INSTRUCTOR_ID
JOIN COURSE b ON w.COURSE_NO = b.COURSE_NO
WHERE UPPER(DESCRIPTION) like '%JAVA%'
GROUP BY z.FIRST_NAME,z.LAST_NAME,b.COURSE_NO
)
SELECT first_name, last_name, course_no, description
FROM q
WHERE TheCount = (SELECT MAX(TheCount) FROM q);
Note this may give you more than one instructor.
Also, I've compared the course description search string using all upper case to eliminate the possibility of missing a course because of JAVA being in a different case.
EDIT:
There are a number of SQL functions that can be used as "Analytic" functions - where the function is applied to the records that fall within a "window", i.e., the PARTITION BY clause. Some of them are sensitive to ordering as well, and an ORDER BY clause can be used as well. You can find some good reference material here at Tim Hall's site. Another is at Shouvik Basu's blog.

Query - limit the number of classes a teacher can teach

I am working on my senior Project. A mini version of an online registration system and website. In the assumptions we want to limit the number of classes a teacher can teach in a semester to 3.
TblEmployee contains: emp_ID (key), can_Teach (first 4 letters of topic).
TblCourse contains: course_ID (Key), course_Type (first 4 letters of topic).
TblClass contains: ClassID (Key), emp_ID (FK), course_ID (FK) semester (period of time)
So far this works fine in selecting the proper teacher that teaches that class:
SELECT *
FROM tblEmployee, tblCourse
WHERE tblEmployee.canTeach = tblCourse.course_Type
AND tblClass.course_ID = ?
However I want to add to it that from tblClass if emp_ID (COUNT) < 3 to include those and exclude those greater than or equal to 3 (i.e. they will not show up in the drop down list.
I tried this but it did not work.
SELECT *
FROM tblEmployee, tblCourse
WHERE tblEmployee.canTeach = tblCourse.course_Type
AND tblClass.course_ID = ?
INNER JOIN (SELECT
tblEmployee.emp_ID, tblClass.emp_ID
FROM
tblEmployee, tblClass
GROUP BY
tblClass.emp_ID
HAVING
count(*) < 3 AND tblClass.emp_ID = tblEmployee.emp_ID)
and semester = ?
Any help would be appreciated.
I would start on the sub query, slim it down, and make your syntax consistent.
SELECT
tblClass.emp_ID
FROM
tblClass
where semester = ?
GROUP BY
tblClass.emp_ID
HAVING count(tblClass.emp_ID) < 3
As I understand it, that is IDs which are in the table less than 3 times (teachers that are teaching less than 3 courses).
For your outer query, you want employees that meets its criteria but are also in the inner set. Again, make your syntax consistent. Then try an IN.
SELECT *
FROM tblEmployee inner join tblCourse
on tblEmployee.canTeach = tblCourse.course_Type
where tblClass.course_ID = ?
and tblEmployee.emp_id
in
{
SELECT
tblClass.emp_ID
FROM
tblClass
where semester = ?
GROUP BY
tblClass.emp_ID
HAVING count(tblClass.emp_ID) < 3
}
See what that does.

cant understand how this view in SQL works

I am having a hard time understand how the create view, TRANSCRIPTVIEW, manages to set the grade of 0 for those who did not take a course. An explanation would help, the solution and question is below. Thanks.
Student(Id,Name)
Transcript(StudId,CourseName,Semester,Grade)
Formulate the following query in SQL:
Create a list of all students (Id, Name) and, for each student, list the average grade for the courses taken in the S2002 semester.
Note that there can be students who did not take any courses in S2002. For these, the average grade should be listed as 0.
Solution:
We first create a view which augments TRANSCRIPT with rows that enroll every student into a NULL course with the grade of 0. Therefore, students who did not take anything in semester ’S2002’ will have the average grade of 0 for that semester.
Below is what confuses me, how does this work and why does it work?
CREATE VIEW TRANSCRIPTVIEW AS (
( SELECT * FROM Transcipt)
UNION
(
SELECT S.Id,NULL,’S2002’,0
FROM Student S)
WHERE S.Id NOT IN (
SELECT T.StudId
FROM Transcript T
WHERE T.Semester = ’S2002’) )
)
Remaining solution:
SELECT S.Id, S.Name, AVG(T.Grade)
FROM Student S, TRANSCRIPTVIEW T
WHERE S.Id = T.StudId AND T.Semester = ’S2002’ GROUP BY S.Id
how the create view, TRANSCRIPTVIEW, manages to set the grade of 0 for those who did not take a course
The set of students who did not take a course in semester S2002 have no record in the transcript table for that semester. Those who did take a course in that semester do have a record in the table for that semester. The query supplies values NULL, 'S2002',0 for students if they are not in the Transcript table for semester S2002:
SELECT S.Id,NULL,’S2002’,0 FROM Student S) -- this parenthesis is wrong
-- this following where conditions looks for students NOT IN the 2002 subset:
WHERE S.Id NOT IN
-- this next part gets a list of studentids for semester 2002
(
SELECT T.StudId FROM Transcript T
WHERE T.Semester = ’S2002’
)
The solution in your qusetion is ridiculous. The better solution is:
SELECT S.Id, S.Name, AVG(case when T.Semester = ’S2002’ then T.Grade end) as AvgS2002Grade
FROM Student S left outer join
TRANSCRIPTVIEW T
on S.Id = T.StudId AND T.Semester = ’S2002’
GROUP BY S.Id
The query in your question is overly complicated. It is using a union (which should really be union all for performance reasons) to be sure all students are included. Gosh, this is what left outer join is for. It is doing filtering in the where clause, when a conditional aggregation is more suitable. It uses archaic join syntax, instead of the ANSI standard.
I hope you are not learning SQL with those shortcomings.