Joining two indirectly related tables without including columns from tables in between - sql

Based on the following ERD, I'm trying to write a query that displays reservations made directly by customers and include reservation id, reservation date, customer id, customer first name, tour trip id, tour category name, tour trip date
I've been able to include everything in my query except for the tour category name because the TOUR_SITES table is in the way. Is there a way I can join the category name from the TOUR_PACKAGE table without adding any extra columns?
SELECT r.RESERVATION_ID, r.RESERVATION_DATE,
c.CUSTOMER_ID, c.FIRST_NAME,t.TRIP_ID, o.TRIP_DATE/*, P.CATEGORY_NAME*/
FROM CUSTOMER c
INNER JOIN RESERVATION r
ON
r.CUSTOMER_ID=c.CUSTOMER_ID
INNER JOIN TOURTRIP_RESERVATION t
ON
r.RESERVATION_ID=t.RESERVATION_ID
INNER JOIN TOUR_TRIP O
ON
t.TRIP_ID=o.TRIP_ID
WHERE AGENT_ID IS NULL;

Is there a way I can join the category name from the TOUR_PACKAGE table without adding any extra columns?
Sure; just join all tables you need. You don't have to add additional columns (the ones you don't need) into the select column list, but you do have to use the tour_sites table anyway.
Something like this:
select r.reservation_id, r.reservation_date,
c.customer_id, c.first_name,t.trip_id, o.trip_date,
p.category_name
from customer c inner join reservation r on r.customer_id=c.customer_id
inner join tourtrip_reservation t on r.reservation_id=t.reservation_id
inner join tour_trip o on t.trip_id=o.trip_id
--
join tour_sites s on s.tour_siteid = o.tour_siteid --> add
join tour_package p on p.category_id = s.category_id --> this
where agent_id is null;

You need to first join tour_sites with tour_trip on TOUR_SITEID and then join tour_package with tour_sites on category_id to get the tour category_name. You can join left join on tour_sites in case there are no tour sites assigned for a tour trip like a newly added tour_trip.
SELECT r.RESERVATION_ID, r.RESERVATION_DATE, c.CUSTOMER_ID, c.FIRST_NAME,t.TRIP_ID, o.TRIP_DATE,TP.CATEGORY_NAME
FROM CUSTOMER c
INNER JOIN RESERVATION r ON r.CUSTOMER_ID=c.CUSTOMER_ID
INNER JOIN TOURTRIP_RESERVATION t ON r.RESERVATION_ID=t.RESERVATION_ID
INNER JOIN TOUR_TRIP O ON t.TRIP_ID=o.TRIP_ID
LEFT JOIN TOUR_SITES TS ON TS.TOUR_SITEID = O.TOUR_SITEID
INNER JOIN TOUR_PACKAGE TP ON TP.CATEGORY_ID = TS.CATEGORY_ID
WHERE AGENT_ID IS NULL;

Related

How to combine Inner Join and Left Join in SQL Query statement?

Given this Diagram:
What is the right way to use join that will includes all necessary fields from different tables (person name, employee number, status of contracts, job name, department name, pcn/item name, country, and religion)? BUT I want also to include all persons that choose not to put either thier country or religion. I have this query:
SELECT persons.fullname, religions.religion_name, countries.country_name
FROM countries INNER JOIN (religions INNER JOIN (persons INNER JOIN
((jobs INNER JOIN (departments INNER JOIN pcns ON departments.ID = pcns.department_id) ON jobs.ID = pcns.job_id)
INNER JOIN (employees INNER JOIN contracts ON employees.ID = contracts.employee_id) ON pcns.ID = contracts.pcn_id)
ON persons.ID = employees.person_id) ON religions.ID = persons.religion) ON countries.ID = persons.country_id;
I used LEFT JOIN but I got an error. Right now, I only query all my tables except for countries and religions then I made a function that whenever a user clicks particular person this function will return its religion and/or country. I am just curious how to achieve it in a SELECT query.

How to inner join with multiple tables for 3NF Normalization in SQL

I am trying to create normalization 3 nf (normal form) in this database. However, when I execute the query, the table is empty. As you will see, this is my table and diagram.
Here is the relationship that we want to 3NF
Torder->(Customer-Food-Carrier-Waiter)-(Ternary Relationship)-(Customer_id,Food_id,Carrier_id,Waiter_id)
Here is my query
SELECT
Customers.ID AS CustomerID,
Food.ID AS FoodID,
Carrier.ID AS CarrierID,
Waiter.ID AS WaiterID,
tOrder.ID AS TORDERID
FROM
tOrder
INNER JOIN
Customers ON Customers.ID = tOrder.Customer_id
INNER JOIN
Food ON Food.ID = tOrder.Food_id
INNER JOIN
Carrier ON Carrier.ID = tOrder.Carrier_id
INNER JOIN
Waiter ON Waiter.ID = tOrder.Waiter_id
ORDER BY tOrder.ID;
Clearly, you have an issue where some of the tables are empty or the ids do not match. You can use LEFT JOIN to keep all orders and see what is happening:
FROM tOrder o LEFT JOIN
Customers c
ON c.ID = o.Customer_id LEFT JOIN
Food f
ON f.ID = o.Food_id LEFT JOIN
Carrier ca
ON ca.ID = o.Carrier_id LEFT JOIN
Waiter w
ON w.ID = o.Waiter_id
If there are no matches, then the orders are still in the results, with NULL for the values in the table with no matches.
Note that this also introduces table aliases, so the query is easier to write and to read.

How can I connect multiple tables using an inner join?

I am trying to select and print customer_name(customer table), room_number(room table), room_rate (room table),rate_type(reservation table), checkin_date(reservation table), checkout_date(reservation table), billing_amount(billing table) from multiple tables. I tried to do an inner join but the error is 'column ambiguously defined '
SELECT *
FROM Customer c
INNER JOIN Reservation r
ON c.customer_id = r.customer_id
INNER JOIN Room s
ON s.room_id = r.room_id
INNER JOIN billing b
ON reservation_id = b.reservation_id
WHERE c.customer_name = 'John Scott';
You're missing the table alias on the left side of the last JOIN. Try this:
SELECT *
FROM Customer c
INNER JOIN Reservation r
ON c.customer_id = r.customer_id
INNER JOIN Room s
ON s.room_id = r.room_id
INNER JOIN billing b
ON r.reservation_id = b.reservation_id
WHERE c.customer_name = 'John Scott';
One problem is in your join and one in your select:
SELECT *
-------^ duplicate column names
FROM Customer c INNER JOIN
Reservation r
ON c.customer_id = r.customer_id INNER JOIN
Room s
ON s.room_id = r.room_id INNER JOIN
billing b
ON reservation_id = b.reservation_id
--------^ missing table alias
WHERE c.customer_name = 'John Scott';
If the only duplicate columns are the JOIN keys, then the USING clause (standard but not supported by all databases) is a handy way to get all the columns:
SELECT *
FROM Customer c INNER JOIN
Reservation r
USING (customer_id) INNER JOIN
Room s
USING (room_id) INNER JOIN
billing b
USING (reservation_id)
WHERE c.customer_name = 'John Scott';
When you using USING, the key columns are not duplicated with SELECT *.

Insert Multiple Tables into one Table

Http://i.stack.imgur.com/z0fSP.png
Http://i.stack.imgur.com/Nd3nB.png
Http://i.stack.imgur.com/5qtRh.png
Http://i.stack.imgur.com/01PVc.png
Http://i.stack.imgur.com/wvibY.png
INSERT INTO OrderArchive
(OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer,ArchiveDate)
SELECT "ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo||' '||Stock.StockDesc,
Orderline.Quantity,
Orderline.UnitPrice,
Person.FirstName||' '||Person.Surname,
Person.FirstName||' '||Person.Surname,
OrderArchive.ArchiveDate
FROM "ORDER"
INNER JOIN Stock
ON Stock.StockNo||' '||Stock.StockDesc = OrderAchive.StockItem
INNER JOIN Orderline
ON Orderline.Quantity = OrderArchive.Quantity
INNER JOIN Orderline
ON Orderline.UnitPrice = OrderArchive.UnitPrice
INNER JOIN Person
ON Person.FirstName||' '||Person.Surname = OrderArchive.SalesRep
INNER JOIN Person
ON Person.FirstName||' '||Person.Surname = OrderArchive.Customer
WHERE "ORDER".OrderDate < DATEADD('M',6,SYSDATE);
I tried to work it out first, but just couldnt manage it .... i am trying to move orders that are older than 6 months to OrderArchive...OrderArchive has OrderNo & Orderdate that come from "ORDER"Table Stock item which is a combination of StockID and Stockdesc from stock table quantity and unit cost are from orderline table salesrep and customer are from person Table and datearchived is a sysdate of the date the order was archived
To do this, you need a way to join the Person record to the TableOrder record. This code assumes you have a PersonID on the TableOrder table. You might have a CustomerID or SalesPersonID or something like that on your TableOrder table to join it to the Person table, but I'm not clear on that.
INSERT INTO ArchiveTable (col_1,col_2,col_3,col_4 etc)
SELECT
o.OrderNo,
o.OrderDate,
p.StockNo||' '||p.StockDesc,
p.FirstName||' '|| p.Surname
FROM TableOrder o
INNER JOIN Person p
ON p.PersonID = o.PersonID
WHERE o.orderdate < DATEADD('M',12,SYSDATE)
I think that you are not getting the expected output from the query, because you are joining the Person table with both SalesRep and Customer names at the same time. Thus, only if an Order has the same name for both SalesRep and Customer, will you get any data. Therefore, I have created different table aliases for the Person table, as below:
INSERT INTO OrderArchive
(OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer,ArchiveDate)
SELECT
"ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo||' '||Stock.StockDesc,
Orderline.Quantity,
Orderline.UnitPrice,
Person_SR.FirstName||' '||Person_SR.Surname,
Person_C.FirstName||' '||Person_C.Surname,
OrderArchive.ArchiveDate
FROM "ORDER"
INNER JOIN Stock
ON Stock.StockNo||' '||Stock.StockDesc = OrderAchive.StockItem
INNER JOIN Orderline
ON Orderline.Quantity = OrderArchive.Quantity
INNER JOIN Orderline
ON Orderline.UnitPrice = OrderArchive.UnitPrice
INNER JOIN Person Person_SR
ON Person_SR.FirstName||' '||Person_SR.Surname = OrderArchive.SalesRep
INNER JOIN Person Person_C
ON Person_C.FirstName||' '||Person_C.Surname = OrderArchive.Customer
WHERE "ORDER".OrderDate < DATEADD('M',6,SYSDATE);
INSERT INTO OrderArchive (OrderNumber,OrderDate,StockItem,Quantity,UnitPrice,SalesRep,Customer)
SELECT "ORDER".OrderNo,
"ORDER".OrderDate,
Stock.StockNo ||' '|| Stock.StockDesc,
Orderline.Quantity,
Stock.UnitCost,
"ORDER".SalesRepID,
Person.FirstName||' '||Person.Surname
FROM Person INNER JOIN
("ORDER" LEFT JOIN
(Orderline INNER JOIN Stock
ON Orderline.StockID=Stock.StockNo)
ON"ORDER".OrderNo=OrderLine.OrderNo)
ON Person.PersonID="ORDER".CustomerID
WHERE "ORDER".OrderDate < ADD_MONTHS (SYSDATE,-6)
ORDER BY "ORDER".OrderNo;
SELECT * FROM OrderArchive;
Nearly Done i just have to get SalesRepID to say firstname surname of salesrep but mostly done :)

Two Inner Joins MYSQL

How would I preform two inner joins in one query?
Ie: three tables
Invoice
Address
Client
Invoice has a column which references an id in clients. It also has a column which references an address. I need to get both the clients name from the matched table and the address from the matched table. How would I INNER JOIN both tables?
I'll add a few details...
invoice has rows address(references address id), client(references client id), id and notes
client has rows first_name, last_name
address has rows street_name and city
I need to pull up
You can have as many JOIN clauses as you need in the query. Each has an ON clause where you specify the related columns between the joined tables.
SELECT
columns
FROM
invoice
INNER JOIN
address
ON
join_condition
INNER JOIN
client
ON
join_condition
Something like:
SELECT
c.*, i.*, a.*
FROM
invoices i
INNER JOIN
client c
ON
i.clientid = c.clientid
INNER JOIN
address a
ON
a.clientid = c.clientid
WHERE
i.id = 21
Don't forget you only select the fields you require, not * (all).
A sample e.g. based on learning from #Dan Grossman above:
SELECT FILM.TITLE, ACTOR.FIRST_NAME, ACTOR.LAST_NAME FROM ACTOR
INNER JOIN FILM_ACTOR
ON ACTOR.ACTOR_ID = FILM_ACTOR.ACTOR_ID
INNER JOIN FILM
ON FILM_ACTOR.FILM_ID = FILM.FILM_ID
WHERE ACTOR.FIRST_NAME = 'Nick' AND ACTOR.LAST_NAME = 'Wahlberg'