How can I SELECT multiple values from 2 tables? SQL Developer - sql

I want to SELECT STAFF_ID, STAFF_NAME and PROJECT_ID. STAFF_ID and PROJECT_ID are linked in a table ASSIGNMENTS, but I want to show that link while also showing the STAFF_NAME for each STAFF_ID from the STAFF table. Here is my code:
CREATE TABLE PROJECT
(PROJECT_ID CHAR(5) NOT NULL,
PROJECT_NAME CHAR(20),
PROJECT_TYPE CHAR(20),
START_DATE DATE,
END_DATE DATE,
PRIMARY KEY (PROJECT_ID));
CREATE TABLE STAFF
(STAFF_ID CHAR(5) NOT NULL,
STAFF_NAME CHAR(20),
JOB_TYPE CHAR(20),
JOB_GRADE CHAR(20),
PRIMARY KEY (STAFF_ID));
CREATE TABLE ASSIGNMENTS
(ASSIGNMENT_ID CHAR(5) NOT NULL,
PROJECT_ID CHAR(5),
STAFF_ID CHAR(5),
PRIMARY KEY (ASSIGNMENT_ID),
FOREIGN KEY (PROJECT_ID) REFERENCES PROJECT(PROJECT_ID),
FOREIGN KEY (STAFF_ID) REFERENCES STAFF(STAFF_ID));
All the tables have been populated with data, and this is the query I've used so far which shows which employees work on a given project (but only with STAFF_ID, not with STAFF_NAME included):
SELECT STAFF_ID, PROJECT_ID
FROM ASSIGNMENTS
WHERE PROJECT_ID = 'B0005';
How can I show the links like this while also including the STAFF_NAME linked to the STAFF_ID from the STAFF table?
Here is some data for a row of each table:
INSERT INTO PROJECT (PROJECT_ID, PROJECT_NAME, PROJECT_TYPE, START_DATE, END_DATE)
VALUES ('B0001','BIKESHOP.COM','WEB DEVELOPMENT',TO_DATE('15/01/17','DD/MM/YY'),TO_DATE('15/02/17','DD/MM/YY'));
INSERT INTO STAFF (STAFF_ID, STAFF_NAME, JOB_TYPE, JOB_GRADE)
VALUES ('ST001','JOHN MASON','WEB DEVELOPER','1');
INSERT INTO ASSIGNMENTS (ASSIGNMENT_ID, PROJECT_ID, STAFF_ID, HARDWARE_ID, SOFTWARE_ID)
VALUES ('A0001','B0001','ST001','H0001','S0001');
What I want to show is PROJECT_ID, STAFF_ID, STAFF_NAME. Just three columns showing those 3 values.

You just need to add join to STAFF table. Something like this
SELECT STAFF.STAFF_ID, STAFF.STAFF_NAME, ASSIGNMENTS.PROJECT_ID
FROM ASSIGNMENTS
INNER JOIN STAFF ON ASSIGNMENTS.STAFF_ID = STAFF.STAFF_ID
WHERE ASSIGNMENTS.PROJECT_ID = 'B0005';

i think this select can solve your problem
select PROJECT_ID, STAFF_ID, STAFF_NAME from ASSIGNMENTS
inner join STAFF on STAFF.STAFF_ID=ASSIGNMENTS.STAFF_ID

For achieving this need, Join the three tables as next approach:
Generic Syntax:
select *
from
tableA a
inner join
tableB b
on a.common = b.common
inner join
TableC c
on b.common = c.common
so follow the next query:
select a.PROJECT_ID, b.STAFF_ID, c.STAFF_NAME
from PROJECT a inner join ASSIGNMENTS b
on a.PROJECT_ID = b.PROJECT_ID
inner join STAFF c
on c.STAFF_ID = b.STAFF_ID
Result:

Related

Oracle - Create A View from Multiple Tables

I am new to SQL and am trying to teach myself different aspects of Oracle as a side interest. While working on a project, it asks to create a view based on the input data from other tables. How would this normally look?
I currently have four tables:
CREATE TABLE Engineers (
EID Integer Primary Key,
LastName varchar(25),
FirstName varchar(25),
Email varchar(255),
Graddate date
);
CREATE TABLE Faculty (
FID Integer Primary Key,
LastName varchar(25),
FirstName varchar(25),
Email varchar(255),
Hiredate date
);
CREATE TABLE Classes (
CID Integer Primary Key,
Subject varchar(6),
Catalognbr varchar(6),
Title varchar(120)
);
CREATE TABLE ClassEnrollments (
EnID Integer Primary Key,
CID Integer,
FID Integer,
EID Integer,
FOREIGN KEY (CID) REFERENCES CLASSES(CID),
FOREIGN KEY (FID) REFERENCES FACULTY(FID),
FOREIGN KEY (EID) REFERENCES ENGINEERS(EID)
);
I am trying to make a view that contains the first and last name of the engineer, last name and email of the faculty member and the subject of a class for a set of inserted data into the ClassEnrollment table which looks like:
INSERT INTO ClassEnrollments
(EnID, CID, FID, EID)
Values (EnID_inc.NEXTVAL, 1, 1, 4);
What I have tried to do was:
CREATE VIEW Testers AS
SELECT e.Lastname, e.Firstname, f.Lastname, f.Email, c.Subject, c.title, en.EnID
FROM Engineers e, Faculty f, Classes c, ClassEnrollments en
WHERE e.EID = en.EID AND f.FID = en.FID AND c.CID = en.CID
ORDER By en.ENID;
However, with this I get a duplicate column name error.
Well, you are not allowed to have duplicate column names in the view. You can use the AS to rename the duplicate columns.
CREATE VIEW Testers AS
SELECT e.Lastname as EngLastname, EngFirstname as FacLastname, f.Lastname as fac_lastname, f.Email, c.Subject, c.title, en.EnID
FROM Engineers e, Faculty f, Classes c, ClassEnrollments en
WHERE e.EID = en.EID AND f.FID = en.FID AND c.CID = en.CID
ORDER By en.ENID;
Your base query would look better if you use a JOIN clause:
SELECT e.Lastname as EngLastname
,e.Firstname as EngFirstname
,f.Lastname as FacLastname
,f.Email
,c.Subject
,c.title
,en.EnID
FROM Engineers e
JOIN Faculty f
ON Faculty.FID = ClassEnrollments.FID
JOIN Classes C
ClassEnrollments.CID = Classes.CID
JOIN ClassEnrollments en
ON ClassEnrollments.EID = Engineers.EID

SQL Query with a count condition

Here is my table structure:
CREATE TABLE CITY(
CITY_ID NUMBER(3) CONSTRAINT CITY_ID_PK PRIMARY KEY,
CITY_NAME VARCHAR2(20) CONSTRAINT CITY_NAME_NN NOT NULL);
CREATE TABLE PILOT(
PILOT_ID NUMBER(3) CONSTRAINT PILOT_ID_PK PRIMARY KEY,
LAST_NAME VARCHAR2(20) CONSTRAINT LAST_NAME_NN NOT NULL,
FIRST_NAME VARCHAR2(20) CONSTRAINT FIRST_NAME_NN NOT NULL,
CITY_ID NUMBER(3) CONSTRAINT CITY_ID_FK REFERENCES CITY(CITY_ID),
SALARY NUMBER(7,2) CONSTRAINT SALARY_CK CHECK (SALARY >= 5000 AND SALARY <= 7000));
CREATE TABLE PLANE(
PLA_ID NUMBER(2) CONSTRAINT PLANE_ID_PK PRIMARY KEY,
PLA_DESC VARCHAR2(20) CONSTRAINT PLANE_DESC_NN NOT NULL,
MAX_PASSENGER NUMBER(3),
CITY_ID NUMBER(3) CONSTRAINT PLANE_CITY_ID_FK REFERENCES CITY(CITY_ID),
CONSTRAINT MAX_PASSENGER_CK CHECK (MAX_PASSENGER <= 500));
CREATE TABLE FLIGHT(
FLIGHT_ID NUMBER(3) CONSTRAINT FLIGHT_ID_PK PRIMARY KEY,
PILOT_ID NUMBER(3) CONSTRAINT FLIGHT_PILOT_ID_FK REFERENCES PILOT(PILOT_ID),
PLA_ID NUMBER(2) CONSTRAINT FLIGHT_PLA_ID_FK REFERENCES PLANE(PLA_ID),
CITY_DEP NUMBER(3) CONSTRAINT FLIGHT_CITY_DEP_FK REFERENCES CITY(CITY_ID),
CITY_ARR NUMBER(3) CONSTRAINT FLIGHT_CITY_ARR_FK REFERENCES CITY(CITY_ID),
DEP_DATE DATE,
DEP_TIME NUMBER(4),
ARR_TIME NUMBER(4),
CONSTRAINT ARR_TIME_CK CHECK (ARR_TIME > DEP_TIME));
The question I have in this lab is to display pilots (ID and Name) who perform two or more flights out of Montreal (It is required that I use the city name in the query and not the ID)
Here is what I have come up with so far:
SELECT PILOT_ID, LAST_NAME, FIRST_NAME
FROM PILOT
JOIN FLIGHT USING (PILOT_ID)
WHERE CITY_DEP=(SELECT CITY_ID
FROM CITY
WHERE CITY_NAME='MONTREAL')
Obviously this gets me part of the answer, but it is not displaying exactly the information I need which is simply the pilots who make this fight >= 2 times.
You can use FETCH ROWS
SELECT PILOT_ID, LAST_NAME, FIRST_NAME
FROM PILOT
JOIN FLIGHT USING (PILOT_ID)
WHERE CITY_DEP=(SELECT CITY_ID
FROM CITY
WHERE CITY_NAME='MONTREAL')
FETCH FIRST 2 ROWS ONLY
Edited with new information on data structure
Understanding your goal
I believe I understand your goal to be querying pilot level data for pilots who have departed from Montreal at least twice in one day.
Query Solution
If my assumptions are true, I believe you can meet your needs by doing something similar to this:
CREATE GLOBAL TEMPORARY TABLE flight_per_day ON COMMIT PRESERVE ROWS AS
SELECT
p.pilot_id,
f.dep_date,
COUNT(CASE WHEN c.city_name = 'MONTREAL' THEN 1 ELSE NULL END) as
montreal_cnt
FROM flights f
LEFT JOIN pilot p ON p.pilot_id = f.pilot_id
LEFT JOIN city c on f.city_dep = c.city_id
GROUP BY 1, 2;
SELECT
p.pilot_id,
p.first_name,
p.last_name
FROM flight_per_day fp
LEFT JOIN pilot p ON p.pilot_id = fp.pilot_id
WHERE fp.montreal_cnt>=2
or without a temp table you could do
SELECT
p.pilot_id,
p.first_name,
p.last_name
FROM
(SELECT
p.pilot_id,
f.dep_date,
-- Find the total number of flights (COUNT) where (CASE WHEN) a flight departs from Montreal (THEN) count it otherwise (ELSE) ignore it (NULL)
COUNT(CASE WHEN c.city_name = 'MONTREAL' THEN 1 ELSE NULL END) as
montreal_cnt
FROM flights f
-- Join in pilot table to get the counts by pilot_id
LEFT JOIN pilot p ON p.pilot_id = f.pilot_id
-- Join in city table to get city_name instead of city_id
LEFT JOIN city c on f.city_dep = c.city_id
GROUP BY 1, 2) fp
LEFT JOIN pilot p ON p.pilot_id = fp.pilot_id
-- Only give me the data for pilots who have flown out of Montreal at least twice in one day
WHERE fp.montreal_cnt>=2
For each pilot, you need to count how many flights that pilot has from Montreal, and then retrieve the pilots that have 2 or more flights. This is a job for GROUP BY and HAVING.
SELECT PILOT_ID, LAST_NAME, FIRST_NAME
FROM PILOT
JOIN FLIGHT USING (PILOT_ID)
JOIN CITY ON (CITY_DEP = CITY_ID)
WHERE CITY_NAME='MONTREAL'
GROUP BY PILOT_ID, LAST_NAME, FIRST_NAME
HAVING COUNT(*) >= 2;

fetching only values that does not contain a particular value in any of its row

my requirement was to list all prescriptions done by the doctors who at least one time prescribed the drugs supplied by
the company kleen. List a name of doctor, drug name, patient
name, and date of prescription.
so for example if the data stored within the database was like this
CREATE TABLE DOCTOR (
DID VARCHAR2(20)
CONSTRAINT Doctor_DID_NotNull NOT NULL,
DName VARCHAR2(50),
Speciality VARCHAR2(70),
YearOfExp Number,
CONSTRAINT Doctor_PK PRIMARY KEY (DID)
);
CREATE TABLE PATIENT (
PID VARCHAR2(20)
CONSTRAINT PATIENT_PID_NotNull NOT NULL,
PName VARCHAR2(50),
PDOB DATE,
PAddress VARCHAR2(70),
PPostalcode VARCHAR2(12),
FamilyDoctor VARCHAR2(20),
CONSTRAINT Patient_PK PRIMARY KEY (PID),
CONSTRAINT Patient_FK FOREIGN KEY (FamilyDoctor) REFERENCES DOCTOR (DID)
);
And this was what I had used to fetch the data
SELECT dr.DName, pr.Tradename, pa.PName, pr.PrescDT
FROM PRESCRIPTION pr, DOCTOR dr, PATIENT pa
WHERE pr.PharName ='kleen'
AND pr.DID = dr.DID
AND pr.PID = pa.PID;
But it only return to me saying that no rows were selected. How do i phrase it then, such that I will get the results that I want.
I am not sure I correctly understood your question but I think you can try following query. Pls try to post sample data and desired output (text formatted). Contact for any problem.
SELECT dr.DName, pr.Tradename, pa.PName, pr.PrescDT
FROM DOCTOR dr
INNER JOIN (SELECT DISTINCT dr.DID
FROM PRESCRIPTION pr
INNER JOIN DOCTOR dr ON pr.DID = dr.DID
WHERE pr.PharName ='kleen') dr2 ON dr.DID = dr2.DID
INNER JOIN PRESCRIPTION pr ON pr.DID = dr.DID
INNER JOIN PATIENT pa ON pr.PID = pa.PID
;
In the patient table, familydoctor is the column name which is referencing to the doctor table, so try as
SELECT dr.dname,
pr.tradename,
pa.pname,
pr.prescdt
FROM prescription pr
JOIN doctor dr
ON ( pr.did = dr.did )
JOIN patient pa
ON ( dr.did = pa.familydoctor)
WHERE LOWER(pr.pharname) = LOWER('kleen');
If needed add LEFT OUTER JOIN or RIGHT OUTER JOIN as per your requirement.
Ideally, you should provide columns and sample data for all three tables, then it would be better to analyse the problem.

views/ queries for multiple foreign keys referencing same primary keys

Hello I have got two tables and the staff_id from the risk table is used to look up the name of the owner and contact person. I was wondering if it is possible to create a view which includes both the owner name and staff name. I tried to create a view as shown below but I could only include either owner name or contact name in the view. (For reference I am using derby). Thanks in advance.
CREATE VIEW public_view AS
SELECT r.risk_id, r.risk_name s.staff_name
FROM risk r, staff s
AND r.owner_id = s.staff_id;
CREATE TABLE STAFF
(
staff_id varchar(8) NOT NULL,
staff_name varchar(100),
staff_email_addr varchar(30),
staff_position varchar(30),
staff_sect_elem varchar(60),
CONSTRAINT pk_staff_id PRIMARY KEY (staff_id)
);
CREATE TABLE RISK
(
risk_id varchar(6) NOT NULL,
risk_name varchar(20) NOT NULL,
risk_desc varchar(20),
owner_id varchar(8),
contact_id varchar(8),
CONSTRAINT pk_risk_id PRIMARY KEY (risk_id),
CONSTRAINT fk_owner_id FOREIGN KEY (owner_id) REFERENCES STAFF(staff_id),
CONSTRAINT fk_contact_id FOREIGN KEY (contact_id) REFERENCES STAFF(staff_id)
);
Use table aliases:
select *
from RISK r
LEFT OUTER JOIN STAFF o ON r.owner_id = o.staff_id
LEFT OUTER JOIN STAFF c ON r.contact_id = c.staff_id
You were close. You need to create a table with data from both tables using a join, in this case joining on fk:
CREATE VIEW public_view AS
SELECT r.risk_id, r.risk_name s.staff_name
FROM risk r
LEFT JOIN staff s
ON r.owner_id = s.staff_id;
Left join will not pull data that is in Staff table but not in Risk table.
This is what I ended up doing
CREATE VIEW public_view1 (risk_id, risk_name, owner_name, contact_name) AS
SELECT r.risk_id, r.risk_name, o.staff_name, c.staff_name
FROM risk r
LEFT OUTER JOIN staff o ON r.owner_id = o.staff_id
LEFT OUTER JOIN staff c ON r.contact_id = c.staff_id;

Trying to do a three table join displaying all columns

I am trying to do a three table join to display all columns. Only two of the tables have a key in common. Below is the code for the tables I already have:
CREATE TABLE Faculty (
FacultyID int,
FirstName varchar(30),
LastName varchar(30),
EMail varchar(60),
BirthDate DATE,
Numbr_Courses int,
PRIMARY KEY (FacultyID)
);
CREATE TABLE Courses(
CourseID int,
CourseDisc varchar(4),
CourseNum varchar(4),
NumbrCred varchar(1),
FirstYrOffered int,
CourseTitle varchar(75),
PRIMARY KEY (CourseID)
);
CREATE TABLE Faculty_Courses(
InstanceID int,
FacultyID int,
CourseDisc varchar(4),
CourseNum varchar(4),
CourseTitle varchar(75),
PRIMARY KEY (InstanceID),
FOREIGN KEY (FacultyID) REFERENCES Faculty(FacultyID)
);
The two tables that have the same key is Faculty and Faculty_Course. I have attempted one peice of code that only gave me back an error. I guess I am having real trouble understanding how to do proper code for joining tables. My attempted code is below:
SELECT Faculty.*, Faculty_Courses.*
FROM Faculty INNER JOIN Courses
ON Faculty.FacultyID=Faculty_Courses.FacultyID
This gave me back the following error:
ERROR 1066 (42000): Not unique table/alias: 'Faculty'
Any help will be appreciated.
I would change your Faculty_Courses table:
CREATE TABLE Faculty_Courses(
InstanceID int,
FacultyID int,
CourseID int,
PRIMARY KEY (InstanceID),
FOREIGN KEY (FacultyID) REFERENCES Faculty(FacultyID),
FOREIGN KEY (CourseID) REFERENCES Courses(CourseID)
);
And then join all three tables together:
SELECT F.*, FC.*, C.*
FROM Faculty F
INNER JOIN Faculty_Courses FC ON F.FacultyID = FC.FacultyID
INNER JOIN Courses C ON C.CourseID = FC.CourseID
You probably only really want some of the columns from F (Faculty) and C (Courses) and can mostly ignore the FC columns as they are just used for mapping between F and C
I'm surprised your factory_courses table doesn't have a reference to courses.
Either way, with your current query, you are selecting from faculty and courses but aliasing faculty_courses -- you cannot do that. This is what your current query should look like:
select *
from faculty f
join faculty_courses fc on f.facultyid = fc.facultyid
To join the 3rd table, if you had a courseid in your faculty_courses table, perhaps something like this:
select *
from faculty f
join faculty_courses fc on f.facultyid = fc.facultyid
join courses c on fc.courseid = c.courseid
A Visual Explanation of SQL Joins
You're doing a join on two tables without actually linking two columns from those tables; joining Faculty and Courses using columns from Faculty and Faculty_Courses.
Since no column exists with unique values linking Courses with any other table, you cannot perform a join with Courses.
So you should join Faculty and Faculty_courses:
SELECT Faculty.*, Faculty_Courses.*
FROM Faculty INNER JOIN Faculty_Courses
ON Faculty.FacultyID=Faculty_Courses.FacultyID