Query - limit the number of classes a teacher can teach - sql

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.

Related

How do i make this query with two conditions?

database structure
Professor
prof_id number
name string
salary number
building string
Course
name string
prof_id number
room_number number
start_time number
end_time number
Room
room_number number
capacity number
building string
Professors with at least 1 math course:
select distinct Professor.name, count(Course.name) AS numberOfMathCourses
from Course
LEFT JOIN Room
ON Course.Room_id = Room.Room.id
INNER JOIN Professor
ON Professor.id = Course.id
where Course.name = 'math'
group by Professor.name
having numberOfMathCourses > 0
Professors with less than 3 courses :
select distinct Professor.name, count(Course.name) AS numberOfCourses
from Course
LEFT JOIN Room
ON Course.Room_id = Room.Room.id
INNER JOIN Professor
ON Professor.id = Course.id
group by Professor.name
having numberOfCourses < 3
how would do I create a Query that has both of these conditions ? more than one math course course and less than 3 courses.
I tried sub-queries but I wasn't able to make it work. I will try to look into it more. Thanks for the help.
select *
from Professor p
where
(select count(*) from Course c where p.prof_id = c.prof_id and c.name = 'math') > 0
and (select count(*) from Course c where p.prof_id = c.prof_id) < 3

How to query for many to many relationship in Sql Server

Here is my tables
My question is How to get CourseNames for a specific student id
I tried this but didn't work
select Course.CourseName from Course
where Course.CourseId in (
select Student.studentname ,StudentCourse.CourseId from Student inner join StudentCourse
on Student.StudentId = StudentCourse.StudentId
where Student.StudentId = 1)
You can forget my query because i am new in SQL Server just tell me what exactly developers do in SQL Server real-world to get course names of a specific student
As you said you want to know the approach this is just basic viewpoint
1) We want to look at CourseName's.
SELECT CourseName FROM Course
2) One Student may have more than one Courses.
3) So we have one more table which is StudentCourse to achieve this.
4) We have to look CourseName's ID'S in this table
SELECT CourseID FROM StudentCourse
5) to find which students(X is a number you seach for) takes those courses.
WHERE StudentID = X
6) If we look them together, we now have all CourseName's via step 1. But we don't want all CourseName's and we have all CourseID's which X numbered student takes. So if we get them together, now we will just select CourseName's which X takes.
WHERE CourseID IN
7) So our final result is
SELECT CourseName FROM Course WHERE CourseID IN
(SELECT CourseID FROM StudentCourse WHERE StudentID = X)
Check this or this one to see how it works.
I'm using left joins just in case your student doesn't have any courses assigned, otherwise, if you use inner joins, you'll get no results;
SELECT
s.StudentID
,s.StudentNam
,sc.CourseID
,c.CourseName
FROM Student s
LEFT JOIN StudentCourse sc
ON s.StudentID = sc.StudentID
LEFT JOIN Course c
ON sc.CourseID = c.CourseID
WHERE s.StudentID = 1
try this:
select CourseName from Course
where CourseId in
(select CourseId from StudentCourse
where StudentId = 1)

SQL query to get most recent row

I have a Student History table which maintains the enrolled section history for each student. For example, Student X is presently in Section 1 and Student X may have been in other sections in the past (including past enrollment in Section 1).
Each time Student X changes to another section a record is added to the Student History table.
The Student History table has following structure:
Student Id, Date_entered, section_id
I need to write a SQL query to get the records for the following scenario:
Get Student Id of all students CURRENTLY in Sections 1 & 2 (Students most recent date_entered must have been either Sections 1 or 2). The results should not include any students who were in these sections 1 & 2 in the past.
Sample Query:
select student_id from student_Queue_history where section_id in (1, 2)
Can someone help me write query for this one?
You can first select max date for each student and join it back to the student_history table.
with maxdate as (
select student_id, max(date_entered) as mxdate
from student_history
group by student_id)
select s.*
from student_history s
join maxdate m on s.student_id = m.student_id and s.date_entered = m.mxdate
where s.section_id in (1,2)
You have some pretty challenging design flaws with your table but you can leverage ROW_NUMBER for this. This is not the best from a performance perspective but the suboptimal design limits what you can do. Please realize this is still mostly a guess because you haven't provided much in the way of details here.
with CurrentStudents as
(
select *
, ROW_NUMBER() over(partition by student_id order by date_entered desc) as RowNum
from student_Queue_history
)
select *
from CurrentStudents
where section_id in (1, 2)
and RowNum = 1
select a.student_id
from student_Queue_history as a
where a.section_id in (1, 2)
and not exists (select b.student_id from student_Queue_history as b where b.student_id = a.student_id and b.Date_entered > a.Date_entered)

select ... not exists not exists query

select r.index, sum(c.points)
from records r join exams e2 on r.index = e2.index
join courses c on c.id_course = e2.id_course
where not exists ( select *
from required_courses rs
where rs.id_studie = r.id_studie
and not exists (select *
from exams e
where e.id_course = rs.id_course
and r.index = e.index
and score>5))
and score>5
group by index;
I have that query. I know what it does, but don't know how.
I have relativly big database with 16 tables, but only use 4 in this query.
Used tables are:
RECORDS (of students) [index (pr. key), name, surname, ..., id_studie(1)(for. key)]
EXAMS [index(of students) (p.k.), id_course(p.k.),..., score(2), application_status]
COURSES [id_course(p.k.), ..., points]
REQUIRED_COURSES [id_studie (f.k.), id_course(f.k), ...]
(1) I don't know better word in English. When on some faculty there are Informatics, Math, Physics, etc. classes. Informatics is one studie.
(2) Scores go from 5 to 10. 10 is best. At least 6 is required for passing.
Query:
- Find all students that passed all required exams on studie thay studie. Print indexes and number of points.
My question: Can sameone explain how does this work in simple words?
I don't understand not exists & not exists part.
Sorry for my bad english.
Always analyze the query from the inside out.
Innermost query:
Select the exams with score higher than 5
Middle one:
Select the required courses that don't have an exam with score higher than 5
Outer one:
Select students that don't have a required course that doesn't have the exam with score higher than 5
The example is a double-nested NOT EXISTS query.
If a subquery returns any rows at all, EXISTS subquery is TRUE, and NOT EXISTS subquery is FALSE.
That is, it has a NOT EXISTS clause within a NOT EXISTS clause.
It is easier to say that a nested NOT EXISTS answers the question “is x TRUE for all y?”
--Part 3
SELECT r.index,
SUM(c.points)
FROM records r
join exams e2
ON r.index = e2.index
join courses c
ON c.id_course = e2.id_course
WHERE NOT EXISTS (
--Part 2 starts
SELECT *
FROM required_courses rs
WHERE rs.id_studie = r.id_studie
AND NOT EXISTS (
--Part 1 starts
SELECT *
FROM exams e
WHERE e.id_course = rs.id_course
AND r.index = e.index
AND score > 5
--Part 1 ends
)
--Part 2 ends
)
AND score > 5
GROUP BY index;
--Part 3 ends
Part 1: Fetch all records of students from EXAMS table who scored more than 5. You should get all pass mark students for all courses here
Part 2: Join Part1 results with REQUIRED_COURSES on student id and fetch all the required courses where the student has not cleared the exams (where student does not have a score more than 5). You should have all the student's courses name where they are not successful
Part 3: Join Part 2 results with RECORDS table on index and also COURSES table on course id to fetch the index and sum of points. You can see this part into two pieces. First is the normal JOIN with two tables and then the NOT EXISTS with the part 2. When you apply a NOT EXISTS on part 2, you are going to get all successful student ids which would provide you the successful entries by adding another SCORE > 5 condition at the end.

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.