Querying from two tables in Oracle Database - sql

I have two tables where I have students details and other table consists of the details of TAs. Tables are as follows:
Students(B#, first_name, last_name, status, GPA, email, bdate, dept)
TAs(B#, ta_level, office)
Now, For each TA from the CS department, find his/her B#, first name, last name, and birth date. I have tried the following query:
select Students.B#, Students.FIRST_NAME, Students.LAST_NAME, Students.BDATE
from Students INNER JOIN TAs ON Students.B# = TAs.B#;
but I have to get only those TAs who are studying in Computer Science. I am using Oracle DB. How will I add another condition after inner join?

For each TA from the CS department
Is there a table or a column specify if a student is studying Computer Science ? however as per your question it seems from the department you can know that.
You can do the below:
select Students.B#, Students.FIRST_NAME, Students.LAST_NAME, Students.BDATE
from Students INNER JOIN TAs ON Students.B# = TAs.B#
where Students.dept='CS' -- or computer science depending on the value.

Related

SQL connecting 3 seperate tables using procedures

I'm struggling with SQL a bit, so far I have 3 tables:
CUSTOMER
id,
name,
surname,
gender,
birthdate
GENDER
id,
gender
ADRESS
id,
country,
city
I need to create a procedure on connecting these 3 tables into a big one, so it would have (customer id, name, gender, country)
I know that I have to use joins but I am so unfamiliar with SQL.
You should just use a JOIN we use a JOIN on 2 or more tables in order to fetch some common attributes related values of one table that exists in other as together. So, here the sql then would look like. Also you dont require the gender seperate table as you have gender already present in your customer table
Select
c.id, c.name, c.gender, a.country
From CUSTOMER c
Join
Address a
On c.id =a.id

how to count different values from different tuples into the same sceme in sql

I have a table of hospitals details, department details linked to it, types of workers (the staff) in different tables, and their salary information.
I want to extract the following for each hospital: the average and the sum of the salaries, the number of nurses, the number of research doctors and the number of beds in all the departments of a specific hospital.
I built this view of all the workers salary information:
CREATE VIEW workers AS
SELECT hospcod, docsal as sal, 'treatdoc' as typework
FROM doc NATURAL JOIN treatdoc NATURAL JOIN dept
UNION
SELECT hospcod, nursal, 'nurse'
FROM nurse NATURAL JOIN dept
UNION
SELECT hospcod, docsal, 'rsrchdoc'
FROM doc NATURAL JOIN rsrchdoc NATURAL JOIN lab;
the departments and the labs have the hospital code column to correlate a worker information to a specific hospital.
so I have one sceme for all the staff with their rules workers(hospital_code, salary, type_of_worker)
here is the query I'm trying to build:
SELECT hospname, sum(workers.sal), avg(workers.sal), count(dept.numbed),
(SELECT count(typework) from workers where typework = 'nurse') nurse_num,
(SELECT count(typework) from workers where typework = 'rsrchdoc') rsrchdoc_num
FROM hosp NATURAL JOIN dept NATURAL JOIN workers
GROUP BY hospname;
I want to count for each hospital, the number of nurses and the number of research doctors
but it should be correlated somehow to the different hospitals (in the above it gives me the same number of nurses / rsrchdocs for each hospital) , there should be columns that is grouped by hospnames and should get all the tuples like the salary info (avg, sum), as I got properly, but the workers information should be grouped HAVING typework = 'nurse' for the nurse_num, and for the column rsrchdoc_numit should be HAVING typework = 'rsrchdoc_num'
does someone have an idea how can I combine thouse columns in one query?
thank you!
There is an error in your query, I will try to explain.
When you do:
(SELECT count(typework) from workers where typework = 'nurse') nurse_num,
You are getting a constant, that is not affected by the "group by" you are doing after.
What you have to do is a JOIN (like you did in the view) and link the nurse and the rsrchdoc to an specific hospital.
I will give an example is pseudo code
SELECT hosp_name, sum(nurse.salary) , avg(nurse.salary)
FROM hosp
JOIN nurse ON nurse.hosp_name = hosp.hosp_name
GROUP BY hosp.hosp_name
This query will give you 1 row for each nurse in each hospital (assuming that a nurse may work in more than one hospital).
Then you have to do the same thing also for doctors, in a different operation.
SELECT hosp_name, sum(doctors.salary) , avg(doctors.salary)
FROM hosp
JOIN doctors ON doctors.hosp_name = hosp.hosp_name
GROUP BY hosp.hosp_name
And finally you will have to join both ( you may perform the sum first to make it more readable.
SELECT hosp_name, sum_sal_doc, avg_sal_doc, sum_nur_doc, avg_nur_doc
FROM hosp
LEFT JOIN ( SELECT doctors.hosp_name, sum(doctors.salary) as sum_sal_doc, avg(doctors.salary) as avg_sal_doc
FROM doctors
GROUP BY doctors.hosp_name
) t1 ON t1.hosp_name = hosp.hosp_name
LEFT JOIN ( SELECT nurses.hosp_name, sum(nurses.salary) as sum_nur_doc, avg(nurses.salary) as avg_nur_doc
FROM nurses
GROUP BY nurses.hosp_name
) t2 ON t2.hosp_name = hosp.hosp_name
There must be 1 to many relationship between hosp --> dept and hosp --> workers so if you join these 3 tables then you will definitely find the duplicates for dept and workers so you must have to create sub-query for one of the dept or workers to fetch single grouped record group by hospital as follows:
SELECT h.hospname,
sum(w.sal) total_all_worker_sal,
avg(w.sal) avg_all_workers_sal,
d.numbed,
count(case when w.typework = 'nurse' then 1 end) nurse_num,
count(case when w.typework = 'rsrchdoc' then 1 end) rsrchdoc_num
FROM hosp h
JOIN (select hospital_code , sum(numbed) numbed
-- used SUM as numbed must be number of bed in department
-- COUNT will give you only number of department if you use count(d.numbed)
from dept
group by hospital_code) d ON h.hospital_code = d.hospital_code
JOIN workers w ON h.hospital_code = d.hospital_code
GROUP BY h.hospital_code , h.hospname, d.numbed;
-- used h.hospital_code to separate the records if two hospitals have same name

SQL query to filter value using associative entity

I'm working on this educational system in which the professor table stores the subject ID, career and subject are stored in their own tables and I have the career_subject associative entity because the system assume that the same subject may belong to several careers. The tables look something like this:
CAREER(id, name, quota)
SUBJECT(id, name, exam_date)
PROFESSOR(id, name, subject_id)
CAREER_SUBJECT(career_id, subject_id)
So, how do I get the name of the career the professor may teach using SQL?
I'm trying with
SELECT name FROM career
INNER JOIN career_subject ON career_subject.subject_id = career_subject.subject_id
WHERE professor.subject_id = subject.id;
SELECT p.name as 'Professor', c.name as 'Career' FROM professor p
INNER JOIN career_subject cs ON cs.subject_id = p.subject_id
INNER JOIN career c ON c.id = cs.career_id

confusion with empty relations test using 'not exitst'

I'm reading database systems concepts by Hank Korth.The book states the following gives list of all students who have taken all courses offered
in the Biology department.
select distinct S.ID, S.name
from student as S
where not exists (
(
select course id
from course
where dept name = 'Biology'
)
except
(
select T.course id
from takes as T
where S.ID = T.ID
)
);
student(ID, name, dept name, tot cred)
course(course id, title, dept name, credits)
takes(ID, course id, sec id, semester, year, grade)
However, to my understanding, the last subquery finds all students who are taking at least one course, and by doing minus from the first subquery, we are subtracting all biology courses that are currently taken by students, so we will be left with biology courses that are NOT taken by any students(if any).Then when we do 'not exists' with all student ID's, we are looking for student ID's who are not taking those found biology courses plus they can take any course other than biology.But that does not give list of students who are taking all courses offered in biology department.Can someone please explain?
Please Note: I do understand the use if 'not exist' from this
site but I'm not getting the book example.
I think what you are missing is that the NOT EXISTS subquery gets executed independently, for each row returned by the outer query.
Notice that its a correlated subquery. There's a reference to a column from the outer query S.ID.
A single value of S.ID is passed in for each execution of the subquery. So, if a student is taking all of the courses from the Biology department, the EXCEPT operation in the subquery is going to result in an empty set. And the NOT EXISTS will evaluate to TRUE. But if the subquery returns a row, then there's at least on Biology course which a student isn't taking.

Deriving a column's data from a matching column in SQL

So I have a table that has, employee number, employee name, supervisor number.
I want to run a query that will retrieve employee name, employee number, supervisor name and supervisor number. Only one employee doesn't have a supervisor meaning it will have to display nulls. How would I do this? I'm using Oracle SQL Plus. My attempts haven't worked at all! Any help would be much appreciated.
SELECT ename Employee, empno Emp#, super Manager#
FROM emp;
That gets me three of the columns but to be honest I don't even know where to start to get the supervisors names.
It's for university, but I'm studying for a test it's not for an assignment so no cheating happening here :).
The following should work, and give you nulls if the employee has no supervisor:
SELECT empGrunt.ename Employee
, empGrunt.empno EmpNum
, empSuper.ename SupervisorName
, empSuper.empno SupervisorName
FROM emp empGrunt LEFT OUTER JOIN emp empSuper
ON empGrunt.super = empSuper.empno
Assuming that SupervisorNumber is a foreign key relationship back to the Employee table (where it's the EmployeeNumber of the supervisor's record), then you need to use an outer join.
What you need in this case is a left join:
select
e.EmployeeName,
e.EmployeeNumber,
s.EmployeeName as SupervisorName
from Employee e
left join Employee s on s.EmployeeNumber = e.SupervisorNumber