Oracle - Create A View from Multiple Tables - sql

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

Related

SQL Find all courses who have more students enrolled then the allowed enroll_limit for the course

I'm currently taking a database class and I am stuck on a homework problem due tonight
Find the courses given in the ‘Sloan’ building which have enrolled more students than their enrollment limit. Return the courseno, enroll_limit, and the actual enrollment for those courses.
I'm stuck trying to count how many students are in each course.
CREATE TABLE Course (
courseno VARCHAR(7),
credits INTEGER NOT NULL,
enroll_limit INTEGER,
classroom VARCHAR(10),
PRIMARY KEY(courseNo), );
CREATE TABLE Student (
sID CHAR(8),
sName VARCHAR(30),
major VARCHAR(10),
trackcode VARCHAR(10),
PRIMARY KEY(sID),
FOREIGN KEY (major,trackcode) REFERENCES Tracks(major,trackcode) );
CREATE TABLE Enroll (
courseno VARCHAR(7),
sID CHAR(8),
grade FLOAT NOT NULL,
PRIMARY KEY (courseNo, sID),
FOREIGN KEY (courseNo) REFERENCES Course(courseNo),
FOREIGN KEY (sID) REFERENCES Student(sID) );
My current very broken attempt is
SELECT sloancourse.courseno
FROM course sloancourse
WHERE
sloancourse.classroom = 'Sloan'
and sloancourse.courseno IN (
SELECT c.courseno
FROM student s, enroll e, course c
WHERE
c.courseno = e.courseno
and s.sid = e.sid
and sloancourse.courseno = c.courseno
)
;
Find the courses given in the ‘Sloan’ building which have enrolled more students than their enrollment limit. Return the courseno, enroll_limit, and the actual enrollment for those courses.
You would typically join courses and enrollment (using stanard join syntax, with the on keyword), group by course, and finally filter on courses whose student count with a having clause.
select
c.courseno,
c.enroll_limit,
count(*) actual_enrollment
from course c
inner join enroll e on e.courseno= c.courseno
where c.classroom = 'Sloan'
group by c.courseno, c.enroll_limit
having count(*) > c.enroll_limit
Note that you don't need to bring in the student table to get the desired results.
You could try something like this:
SELECT
Course.courseno,
Course.enroll_limit,
Couse.classroom
FROM Course, Enroll
WHERE Course.courseno = Enroll.courseno
AND Course.classroom = 'Sloan'
GROUP BY Course.courseno
HAVING count(*) > Course.enroll_limit
Postgres docs have an example on these aggregate functions: https://www.postgresql.org/docs/current/tutorial-agg.html
Basically, when you group by one or multiple properties, the resulting table will result in a unique row for the property/combination of properties. In this example, you would have one row for each of the courseno unique values (as they are grouped by this value).

Appropriate SELECT Statement

I have the following tables:
CREATE TABLE Subject
(
Subject_Code INTEGER,
Subject_Year VARCHAR (8),
PRIMARY KEY (Subject_Code, Subject_Year),
Teacher_ID INTEGER REFERENCES
);
CREATE TABLE Teacher
(
TeacherID INTEGER PRIMARY KEY,
FirstName TEXT,
Department_ID INTEGER References Academic Department(Department_ID)
);
CREATE TABLE Subject-taken
(
Marks_Obtained INTEGER,
Subject_Code INTEGER REFERENCES subject (Subject_Code),
Candidate_ID INTEGER REFERENCES Candidate (Candidate_ID),
PRIMARY KEY (Subject_Code, Candidate_ID)
);
CREATE TABLE Academic_Department
(
Department_ID INTEGER PRIMARY KEY,
Department_Name TEXT
);
I've already tried the following select statement
SELECT m.subject_code,
MIN (marks_obtained) AS Min_Marks,
MAX (marks_obtained) AS Max_Marks
FROM Subject-taken m, Subject a
GROUP BY m.Subject_Code;
Want to use the join function any suggestions on where to use it in order to join the departments with subjects and students
Make use of joins to link your data between tables. Use group by to make statistics by some fields. You can try something like this:
SELECT
Subjects.Subject_Code,
Subjects.Subject_Name,
Teachers.TeacherID,
Academic_Department.Department_ID,
min(Subject-taken.Marks_Obtained) as min_marks,
max(Subject-taken.Marks_Obtained) as max_marks,
avg(Subject-taken.Marks_Obtained) as avg_marks,
stddev_samp(subject-taken.Marks_Obtained) as stddev_marks
FROM
Subjects LEFT JOIN
Teachers ON Subjects.TeacherID = Subjects.TeacherID LEFT JOIN
Academic_Department ON Teachers.Department_ID = Academic_Department.Department_ID LEFT JOIN
Subject-taken ON Subjects.Subject_Code = Subject-taken.Subject_Code
GROUP BY
Subjects.Subject_Code,
Subject.Subject_Name,
Teacher.TeacherID,
Academic_Department.Department_ID
I don't really know if stddev_samp is the aggregate function you need, stddev_pop is also available. Please refer to this PostgreSQL documentation table to find out.

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

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:

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

SQL Queries for a database

I have an assignment on DB. I am having some problems with my queries. I am new to SQL.
Here's my tables:
CREATE TABLE Employee (
employee_name varchar(20) NOT NULL PRIMARY KEY,
street varchar(30) NOT NULL,
city varchar(20) NOT NULL
)
CREATE TABLE Works
(
employee_name varchar(20) NOT NULL,
department_name varchar(20) NOT NULL,
title varchar(10) NOT NULL,
salary int NOT NULL,
PRIMARY KEY (employee_name),
FOREIGN KEY (employee_name) REFERENCES Employee,
FOREIGN KEY (department_name) REFERENCES Department
)
CREATE TABLE Department
(
department_name varchar(20),
cityvarchar(20),
PRIMARY KEY (department_name)
)
CREATE table Manages(
employee_name varchar(20) not null,
manager_name varchar (20) not null,
PRIMARY KEY(employee_name),
FOREIGN KEY(employee_name) REFERENCES Employee
)
Find employee names who live in different cities from their department.
Here's my code:
SELECT E.employee_name
FROM Employee E
JOIN Department D
ON E.city = D.city
WHERE E.city <> 'Roma';
Find employee names who live in the same city and in the same street with their managers.
Here's my code:
SELECT E.employee_name
FROM Employee E
INNER JOIN Department D
ON E.city = D.city
INNER JOIN Manages M
ON E.employee_name = M.employee_name
WHERE city='Roma' AND street='Main street';
What am I doing wrong?
Thank you in advance! :)
Here's how you might accomplish the first task (employees who live in a city other than that of their department):
SELECT E.employee_name
FROM Employee E JOIN Works W
ON E.employee_name = W.employee_name
JOIN Department D
ON W.departent_name = D.department_name
WHERE D.city <> E.city;
In order to determine the department in which a given employee works, you need to join to the Works table.
I have to admit that the vertical partition of employee data into Employee and Works tables is a bit odd - there is no real reason for these two to be separate tables (it's a 1-1 relationship). For that matter Manages need not be a separate table either.
Hopefully this can get you on the right path for the second query.