How do i make this query with two conditions? - sql

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

Related

SELECT * FROM table in addition of aggregation function

Short context:
I would like to show a list of all companies except if they are in the sector 'defense' or 'government' and their individual total spent on training classes. Only the companies that have this total amount above 1000 must be shown.
So I wrote the following query:
SELECT NAME, ADDRESS, ZIP_CODE, CITY, SUM(FEE-PROMOTION) AS "Total spent on training at REX"
FROM COMPANY INNER JOIN PERSON ON (COMPANY_NUMBER = EMPLOYER) INNER JOIN ENROLLMENT ON (PERSON_ID = STUDENT)
WHERE SECTOR_CODE NOT IN (SELECT CODE
FROM SECTOR
WHERE DESCRIPTION = 'Government' OR DESCRIPTION = 'Defense')
GROUP BY NAME, ADDRESS, ZIP_CODE, CITY
HAVING SUM(FEE-PROMOTION) > 1000
ORDER BY SUM(FEE-PROMOTION) DESC
Now what I actually need is, instead of defining every single column in the COMPANY table, I would like to show ALL columns of the COMPANY table using *.
SELECT * (all tables from COMPANY here), SUM(FEE-PROMOTION) AS "Total spent on training at REX"
FROM COMPANY INNER JOIN PERSON ON (COMPANY_NUMBER = EMPLOYER) INNER JOIN ENROLLMENT ON (PERSON_ID = STUDENT)
WHERE SECTOR_CODE NOT IN (SELECT CODE
FROM SECTOR
WHERE DESCRIPTION = 'Government' OR DESCRIPTION = 'Defense')
GROUP BY * (How to fix it here?)
HAVING SUM(FEE-PROMOTION) > 1000
ORDER BY SUM(FEE-PROMOTION) DESC
I could define every single column from COMPANY in the SELECT and that solution will do the job (as in the first example), but how can I make the query shorter using "SELECT * from the table COMPANY"?
The key idea is to summarize in the subquery to get the total spend for the company. This allows you to remove the aggregation from the outer query:
select c.*, pe.total_spend
from company c join
sector s
on c.sector_code = s.code left join
(select p.employer, sum(e.fee - e.promotion) as training_spend
from person p join
enrollment e
on p.person_id = e.student
group by p.employer
) pe
on pe.employer = c.company_number
where s.sector not in ('Government', 'Defense') and
pe.total_spend > 1000

SQL query - list of items in one table not in another

I need some help with a SQL query. I have a table of courses and a table that contains user id and course id, denoting courses that user has taken (might not have taken any; no entry in that table for that user id).
I need a query to return the list of courses not taken.
Course Category table
CategoryID
Caegory
Courses table
CourseID
CategoryID
CourseName
...
UserCourse table
UserID
CourseID
you can use not exists
Select *
From Courses c
Where Not Exists (Select 1 From UserCourse uc Where uc.CourseID = c.CourseID)
This will just list the course
select *
from Courses C
Left join CourseCategory cc on
cc.CategoryID = c.CategoryID
where CourseID not in (Select CourseID from UserCourse where UserID = 14)
what i need is for a given user id and course category, what courses within that category have not been taken by this user
(This should have been in the request by the way.)
So:
Select from courses.
Limit to the desired category.
Limit to courses not in the set of courses taken by the user.
The query:
select *
from courses
where categoryid = 123
and courseid not in (select courseid from usercourse where userid = 456);
Another way of writing same query, which will perform faster.
select C.CourseID,C.CategoryID
from Courses C
Left join CourseCategory cc on
cc.CategoryID = c.CategoryID
left join UserCourse uc
on C.CourseID=uc.CourseID
where uc.CourseID is null

SQL query using NULL

I have two tables, student and school.
student
stid | stname | schid | status
school
schid | schname
Status can be many things for temporary students, but NULL for permanent students.
How do I list names of schools which has no temporary students?
Using Conditional Aggregate you can count the number of permanent student in each school.
If total count of a school is same as the conditional count of a school then the school does not have any temporary students.
Using JOIN
SELECT sc.schid,
sc.schname
FROM student s
JOIN school sc
ON s.schid = sc.schid
GROUP BY sc.schid,
sc.schname
HAVING( CASE WHEN status IS NULL THEN 1 END ) = Count(*)
Another way using EXISTS
SELECT sc.schid,
sc.schname
FROM school sc
WHERE EXISTS (SELECT 1
FROM student s
WHERE s.schid = sc.schid
HAVING( CASE WHEN status IS NULL THEN 1 END ) = Count(*))
You can use not exists to only select schools that do not have temporary students:
select * from school s
where not exists (
select 1 from student s2
where s2.schid = s.schid
and s2.status is not null
)
You can use a regular join.
SELECT DISTINCT c.schName
FROM Students s
INNER JOIN Schools c ON s.schid = c.schid
WHERE s.status IS NULL

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.

Help construct a query given a schema

Here is the schema for the database: http://i.stack.imgur.com/omX60.png
Question is: How many people have at least five еntitlements?
I've got this, please tell me how wrong it is and fix it.
select count(personId)
from serialNumber_tbl natural join entitlement_tbl
group by personId
having sum(entitlementID) > 5
Thank you.
The condition for at least 5 is >= 5, not > 5
You need to count the distinct ids in the entitlement table, not person
This gives you the persons, next you need to subquery it to find the count of persons.
select count(personId)
FROM
(
select personId
from serialNumber_tbl natural join entitlement_tbl
group by personId
having count(distinct entitlement_id) >= 5
) X
Your request isn't exactly clear. Are you asking for the count of people with more than five entitlement rows whether they exist on multiple serial numbers or not? If so, you could do something like:
Select Count(*) As CountOfPeople
From Person_tbl As P
Where Exists (
Select 1
From serialNumbers As S1
Join entitlement_tbl As E1
On E1.serialNumberId = S.serialNumberId
Where S1.personId = P.personId
Having Count(*) >= 5
)
Or is it that you are asking to find the number of people that have a serialNumber with more than five entitlements? If that is the case, then you could do something like:
Select Count(*) As CountOfPeople
From Person_tbl As P
Where Exists (
Select 1
From serialNumbers As S1
Join entitlement_tbl As E1
On E1.serialNumberId = S.serialNumberId
Where S1.personId = P.personId
Having Count( Distinct S1.serialNumberId ) >= 5
)