Inner join alias's causing issues - sql

I have 4 tables.
create table LOCATION(
loccode Number(2) NOT NULL,
locname Varchar2 (30),
state Varchar2 (10),
population Number(7),
travelcode Number(1),
CONSTRAINT PK_LOCATION PRIMARY KEY (loccode)
);
create table DEPOT(
depid Number(4) NOT NULL,
audit_year Number(4),
address Varchar2 (30),
mgrname Varchar2 (30),
capacity Number(7),
capacity_used Number(7),
mgrgender Varchar2(10),
loccode Number(2) NOT NULL,
CONSTRAINT PK_DEPOT PRIMARY KEY (depid),
CONSTRAINT FK_LOCATION FOREIGN KEY (loccode) REFERENCES LOCATION
create table MANUFACTURER(
manid Number (2) NOT NULL,
manname Varchar2(30),
loccode Number(2) NOT NULL,
CONSTRAINT PK_MANUFACTURER PRIMARY KEY (manid),
CONSTRAINT FK_LOC FOREIGN KEY (loccode) REFERENCES LOCATION
);
create table STOCKITEM(
stkid Number(2) NOT NULL,
stkname Varchar2(30),
sellingprice Number(6,2),
purchaseprice Number(6,2),
depid Number(4) NOT NULL,
manid Number(2) NOT NULL,
CONSTRAINT PK_STOCKITEM PRIMARY KEY (stkid),
CONSTRAINT FK_DEP FOREIGN KEY (depid) REFERENCES DEPOT,
CONSTRAINT FK_MANUFACTURER FOREIGN KEY (manid) REFERENCES MANUFACTURER
);
I am trying to generate a query that lets me see the stock id, stock name, manufacturer location and department location.
This requires 4 inner join clauses.
1 to link stockitem to depot, one to link stockitem to manufacturer, and two unique ones linking location to both depot and manufacturer.
Im using this at the moment;
select
stockitem.stkid as "STOCK ID",
stockitem.stkname as "STOCK NAME",
manloc.locname as "MANUFACTURER LOCATION",
deploc.locname as "DEPOT LOCATION"
from stockitem
inner join depot on stockitem.depid = depot.depid
inner join manufacturer on stockitem.manid = manufacturer.manid
inner join location on location.locid = deploc.locid as deploc
inner join location on location.locid = manloc.locid as manloc
order by stockitem.stkid asc;
however it is spitting back that the string is not properly terminated. Am I missing something here?
If I put the alias's before the 'on' (the deploc and manloc), then I get an error saying that its missing an expected operator...i.e....'on'.
Where am I going wrong with this?

The location table alias's should be after the table name and there should be no AS when aliasing tables (that's an Oracle quirk):
select
stockitem.stkid as "STOCK ID",
stockitem.stkname as "STOCK NAME",
manloc.locname as "MANUFACTURER LOCATION",
deploc.locname as "DEPOT LOCATION"
from stockitem
inner join depot on stockitem.depid = depot.depid
inner join manufacturer on stockitem.manid = manufacturer.manid
inner join location deploc on depot.loccode = deploc.loccode
inner join location manloc on manufacturer.loccode = manloc.loccode
order by stockitem.stkid asc;
You don't actually need the AS when aliasing columns but it makes it read easier.
Note the correct column reference in the location inner joins

Related

SQL join query to library

I have these tables,
CREATE TABLE Book
(
ISBN CHAR(05)NOT NULL,
BKName VARCHAR(20)NOT NULL,
Author VARCHAR(20)NOT NULL,
Price NUMERIC(02)NOT NULL,
CONSTRAINT Book_PK PRIMARY KEY (ISBN)
);
CREATE TABLE Location
(
LoID CHAR(05)NOT NULL,
CityName VARCHAR(15)NOT NULL,
Stoke CHAR(05)NOT NULL,
CONSTRAINT Location_PK PRIMARY KEY (LoID)
);
CREATE TABLE Customer
(
CuID CHAR(05)NOT NULL,
CusName VARCHAR(20)NOT NULL,
RegiDate DATE NOT NULL,
Gender VARCHAR(06)NOT NULL,
TeleNum CHAR(12)NOT NULL,
Address VARCHAR(30)NOT NULL,
CONSTRAINT Customer_PK PRIMARY KEY (CuID)
);
CREATE TABLE BookCopy
(
CopyID CHAR(05)NOT NULL,
ISBN CHAR(05)NOT NULL,
LoID CHAR(05)NOT NULL,
CONSTRAINT pk_BookCopy PRIMARY KEY (CopyID),
CONSTRAINT fk_BookCopy_ISBN_FK FOREIGN KEY (ISBN) REFERENCES Book(ISBN),
CONSTRAINT fk_BookCopy_LoID_FK FOREIGN KEY (LoID) REFERENCES Location(LoID)
);
CREATE TABLE BorrowRecord
(
BrrDate DATE NOT NULL,
RetDate DATE NOT NULL,
BrFee NUMBER(05) NOT NULL,
Cus_Review NUMERIC(02)NOT NULL,
CopyID CHAR(05)NOT NULL,
CuID CHAR(05) NOT NULL,
CONSTRAINT pk_BorrowRecord PRIMARY KEY (CopyID, CuID),
CONSTRAINT fk_BorrowRecord_CopyID_FK FOREIGN KEY (CopyID) REFERENCES BookCopy(CopyID) ,
CONSTRAINT fk_BorrowRecord_CuID_FK FOREIGN KEY (CuID) REFERENCES Customer(CuID) );
This is the task: "write and test a query to list the customer ID and name of every Customer along with the books that they have hired within the past 200 days. Include starting date, ending date, and location name for those hirings. All customer details (ID and name) should be included in the output, whether or not they have actually borrowed any books."
I write a query to list the customer ID and name of every Customer along with the books that they have borrowed within the past 200 days. Include starting date, ending date, and location name for those hirings. This the query for it.
SELECT
BorrowRecord.CuID, Customer.CusName, Book.ISBN, Book.BkName,
BorrowRecord.BrrDate, BorrowRecord.RetDate, Location.CityName
FROM
Book
LEFT JOIN
BookCopy ON Book.ISBN = BookCopy.ISBN
LEFT JOIN
BorrowRecord ON BookCopy.CopyID = BorrowRecord.CopyID
LEFT JOIN
Customer ON BorrowRecord.CuID = Customer.CuID
LEFT JOIN
Location ON Location.LoID = BookCopy.LoID
WHERE
BorrowRecord.BrrDate >= sysdate - 200 ;
But I also need to get all customer details (ID and name) that should be included in the output, whether or not they have actually borrowed any books. How can I do it?
If You want to see all customers independently whether they have borrowed a book or not, it's important that the first LEFT JOIN is based on customers table. In Your script, You start with Book, then join to BorrowRecord and only then have The Customer on the right side of the join. Another point is the WHERE -Condition that excludes all entries of Customer that borrowed a book outside of the 200-days-range. This meand that all records of BorrowRecord are shown (that match to the previous join) but only the customers that are found in a link to BorrowRecords from the past 200 days.
Try the following:
SELECT BorrowRecord.CuID, Customer.CusName, Book.ISBN, Book.BkName,
BorrowRecord.BrrDate,BorrowRecord.RetDate, Location.CityName
FROM Customer
LEFT JOIN BorrowRecord ON BorrowRecord.CuID = Customer.CuID
LEFT JOIN BookCopy ON BorrowRecord.CopyID = BookCopy.CopyID
LEFT JOIN Book ON BookCopy.ISBN= Book.ISBN
LEFT JOIN Location ON Location.LoID = BookCopy.LoID
WHERE ISNULL(BorrowRecord.BrrDate,'') >=sysdate-200 ;

I need to create a view that pre-joins the three tables, including all of the records from student and course tables ( shown below) [duplicate]

This question already has answers here:
Error report - ORA-25155: column used in NATURAL join cannot have qualifier 25155. 00000 - "column used in NATURAL join cannot have qualifier"
(2 answers)
Closed 2 years ago.
-- I am trying to create a view for the tables shown below but my attempt is not successfull. I am using Oracle SQL Developer!! Where is the mistake here
CREATE VIEW student_view AS
SELECT Student.*, Course.*, Grade.* FROM (Student NATURAL LEFT OUTER JOIN Grade NATURAL LEFT OUTER JOIN Course)
UNION ALL
SELECT Student.*, Course.*, Grade.* FROM (Course NATURAL LEFT OUTER JOIN Grade NATURAL LEFT OUTER JOIN Student) WHERE Student.StudentID is NULL
;
CREATE TABLE Student(
StudentID INT PRIMARY KEY NOT NULL,
Name CHAR(50),
Address CHAR(50),
GradYear INT
);
-- create table Grade
CREATE TABLE Grade(
CName CHAR(50) NOT NULL,
StudentID INT NOT NULL,
CGrade CHAR(2),
PRIMARY KEY(CName, StudentID)
);
-- create table Course
CREATE TABLE Course(
CName CHAR(50) PRIMARY KEY NOT NULL,
Department CHAR(50),
Credits INT
);
You should create the underlying tables before composing them into a view.
Please follow below sequence,
CREATE TABLE Student(
StudentID INT PRIMARY KEY NOT NULL,
Name CHAR(50),
Address CHAR(50),
GradYear INT
);
-- create table Grade
CREATE TABLE Grade(
CName CHAR(50) NOT NULL,
StudentID INT NOT NULL,
CGrade CHAR(2),
PRIMARY KEY(CName, StudentID)
);
-- create table Course
CREATE TABLE Course(
CName CHAR(50) PRIMARY KEY NOT NULL,
Department CHAR(50),
Credits INT
);
CREATE VIEW student_view AS
SELECT Student.StudentID , Student.Name, Student.Address, Student.GradYear,
Course.CName, Course.CGrade, Grade.Department, Grade.Credits FROM Student
LEFT OUTER JOIN Grade
on (Student.StudentID = Grade.StudentID)
LEFT OUTER JOIN Course
on (Grade.CName = Course.CName);
Corrected version:
Defined tables in the right order
Changed CHAR to VARCHAR2
Added foreign key constraints (inheriting data types)
Removed table aliases not allowed by NATURAL JOIN syntax
Removed redundant brackets from view.
Tables:
create table student
( studentid integer primary key not null
, name varchar2(50) not null
, address varchar2(50)
, gradyear integer );
create table course
( cname varchar2(50) primary key not null
, department varchar2(50)
, credits integer );
create table grade
( cname references course not null
, studentid references student not null
, cgrade varchar2(2) not null
, primary key(cname, studentid) );
View:
create or replace view student_view as
select studentid, name, address, gradyear
, cname, department, credits
, cgrade
from student
natural left outer join grade
natural left outer join course
union all
select studentid, name, address, gradyear
, cname, department, credits
, cgrade
from course
natural left outer join grade
natural left outer join student
where studentid is null;
And just to add, NATURAL JOIN is never a good idea in real code.

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;

JOIN ON SQL syntax

I am taking my first database class and need some info on what I need to change for my script to process. Currently I have 2 tables, an "orders" table and a "customers" table and this is how they are coded.
CREATE TABLE customers (
customer_id INT ,
customer_first_name VARCHAR(20),
customer_last_name VARCHAR(20) NOT NULL,
customer_address VARCHAR(50) NOT NULL,
customer_city VARCHAR(20) NOT NULL,
customer_state CHAR(2) NOT NULL,
customer_zip CHAR(5) NOT NULL,
customer_phone CHAR(10) NOT NULL,
customer_fax CHAR(10),
CONSTRAINT customers_pk
PRIMARY KEY (customer_id)
);
CREATE TABLE order (
order_id INT NOT NULL,
customer_id INT NOT NULL,
order_date DATE NOT NULL,
shipped_date DATE,
employee_id INT,
CONSTRAINT orders_pk
PRIMARY KEY (order_id),
CONSTRAINT orders_fk_customers
FOREIGN KEY (customer_id) REFERENCES customers (customer_id),
CONSTRAINT orders_fk_employees
FOREIGN KEY (employee_id) REFERENCES employees (employee_id)
);
My script to join these two tables together is as follows:
SELECT or.order_id, or.order_date, or.customer_city,
cu.customer_first_name, cu.customer_last_name
FROM orders or INNER JOIN customers cu
ON or.customer_first_name = cu.customer_first_name
AND or.customer_last_name = cu.customer_last_name;
Now obviously, I know it is incorrect and may have multiple errors, so be gentle. I would love to know what I can do to make it work. Please advise.
Two things:
Don't use or as an alias. That's a reserved word.
Join by the foreign key.
The query should look like:
SELECT o.order_id, o.order_date, cu.customer_city,
cu.customer_first_name, cu.customer_last_name
FROM orders o
INNER JOIN customers cu
on o.customer_id = cu.customer_id
You can join your tables on the ID numbers, and you won't have to worry about what happens when multiple people have the same name.
Use this instead:
FROM orders ord INNER JOIN customers cu
ON ord.order_id = cu.customer_id
Your select statement can remain as it is. I also re-aliased according to the comment from Error_2646.
Using a field that is a primary key in one of your tables is also better practice than using non-key fields, when possible.

How can I join two tables but only return rows that match

I have two tables, a property table and a buyer table, I'm trying to write a select script that will show a list of properties that have the same number of rooms as the desired number of rooms of a specified customer.
I think I need to use a inner join to pull the data I need but as I'm still new to this I'm getting a little confused. The select script I have written is as follows,
SELECT DISTINCT Buyer.Buyer_Surname, Buyer.Rooms_Needed, Property.Property_Address as Property_for_sale, Property.Num_Rooms as Property_No_of_Rooms
FROM Buyer
INNER JOIN Property
ON Property.Buyer_ID = Buyer.Buyer_ID
WHERE Buyer.Rooms_Needed = '5'
AND Property.Num_Rooms = '5'
AND Buyer.Buyer_ID = '70000';
however it is telling me no rows are selected but I know there is a buyer requiring 5 bedrooms and 3 properties in the database with 5 bedrooms.
Here are my tables;
CREATE TABLE Buyer
(
Buyer_ID varchar(5) NULL,
Viewing_Data varchar2(50),
Maximum_Budget varchar2(50),
Purchase_Price varchar2(50),
Purchase_Date DATE,
Buyer_Forename varchar2(50),
Buyer_Surname varchar2(50),
Buyer_Address varchar2(50),
Buyer_Town varchar2(50),
Buyer_Postcode varchar2(10),
Rooms_Needed varchar2(10),
Seller_ID Varchar2(5),
Staff_ID varchar2(5),
PRIMARY KEY (Buyer_ID),
FOREIGN KEY (Staff_ID) REFERENCES Staff(Staff_ID),
FOREIGN KEY (Seller_ID) REFERENCES Seller(Seller_ID)
);
CREATE TABLE Property
(
Property_ID varchar(5),
Property_Address varchar(25),
Property_Town varchar(25),
Property_Postcode varchar(25),
Asking_Price varchar2(20),
Date_Registered DATE,
Property_Type varchar2(50),
Num_Rooms varchar2(50),
Buyer_ID varchar(5),
Seller_ID varchar(5),
Branch_ID varchar(5),
PRIMARY KEY (Property_ID),
FOREIGN KEY (Buyer_ID) REFERENCES Buyer(Buyer_ID),
FOREIGN KEY (Seller_ID) REFERENCES Seller(Seller_ID),
FOREIGN KEY (Branch_ID) REFERENCES Branch(Branch_ID)
);
You are selecting on Buyer and Property Ids. You'll be lucky if these line up, but your results still won't be correct. To join the tables where the house has as many rooms as the buyer would like, you need to join on the number of rooms:
SELECT DISTINCT Buyer.Buyer_Surname, Buyer.Rooms_Needed,
Property.Property_Address as Property_for_sale, Property.Num_Rooms as
Property_No_of_Rooms
FROM Buyer
INNER JOIN Property
ON Buyer.Rooms_Needed = Property.Num_Rooms;
If you need to filter by number of rooms, you can also append a WHERE at the end:
... WHERE Buyer.Rooms_Needed = 5;
Try this rather then joining on Buyer.Id and Property.BuyerId
SELECT DISTINCT Buyer.Buyer_Surname, Buyer.Rooms_Needed, Property.Property_Address as Property_for_sale, Property.Num_Rooms as Property_No_of_Rooms
FROM Buyer
INNER JOIN Property
ON Property.Rooms_Needed = Property.Num_Rooms
WHERE Buyer.Buyer_ID = '70000';
This will find all properties with the number of required bedrooms by user id 70000.