To create a view using 5 tables with all columns of all tables - sql

I have to create a view that joins together all of the columns in the CUSTOMERS, ORDERS, ORDERDETAILS, EMPLOYEES, PAYMENTS and PRODUCTS tables.
the schema for the table is below
I tried the following query, though I am at a loss how to solve the above question :
create view orders_view AS
select *
from sys.customers c
left JOIN EMPLOYEES e
on c.SALESREPEMPLOYEENUMBER = e.EMPLOYEENUMBER
left join sys.orders o
on c.CUSTOMER NUMBER = o.CUSTOMERNUMBER
left join sys.orderdetails od
on o.ORDERNUMBER = od.ORDERNUMBER
left join sys.products p
on od.PRODUCTCODE = p.PRODUCTCODE
left join sys.PAYMENTS py
on c.CUSTOMERNUMBER = py.customernumber
I am a newbie with SQL and databases, so any help is appreciated.

Here are some observations on things going wrong:
You have curly braces that are not necessary (perhaps this is a typo in the question).
You are selecting *, but have duplicate column names (such as productcode), which prevents the view from being created. Best practice: list all the columns explicitly in the view.
You have c.CUSTOMER NUMBER = o.CUSTOMERNUMBER. The space is probably a typo. If not, change the name so the space is not part of the name. Best practice: Use identifiers that do not have to be escaped.
I am not aware of a sys.customers table. The sys schema should only be used for internal Oracle objects. (Here is one source.)

thank you for all the inputs. they helped me a lot in figuring out the answer.
Following is the query for the question asked above.it gave me a view with columns from all tables.
create or replace view overall AS
select c.*,
e.LASTNAME,
e.FIRSTNAME,
e.EXTENSION,
e.EMAIL,
e.OFFICECODE,
e.REPORTSTO,
e.JOBTITLE,
o.ORDERNUMBER,
o.ORDERDATE,
o.REQUIREDDATE,
o.SHIPPEDDATE,
o.STATUS,
o.COMMENTS,
od.PRODUCTCODE,
od.QUANTITYORDERED,
od.PRICEEACH,
od.ORDERLINENUMBER,
p.PRODUCTNAME,
p.PRODUCTLINE,
p.PRODUCTSCALE,
p.PRODUCTVENDOR,
p.PRODUCTDESCRIPTION,
p.QUANTITYINSTOCK,
p.BUYPRICE,
p.MSRP,
py.CHECKNUMBER,
py.PAYMENTDATE,
py.AMOUNT
from sys.customers c
left JOIN EMPLOYEES e
on c.SALESREPEMPLOYEENUMBER = e.EMPLOYEENUMBER
left join sys.orders o
on c.CUSTOMERNUMBER = o.CUSTOMERNUMBER
left join sys.orderdetails od
on o.ORDERNUMBER = od.ORDERNUMBER
left join sys.products p
on od.PRODUCTCODE = p.PRODUCTCODE
left join sys.PAYMENTS py
on c.CUSTOMERNUMBER = py.customernumber
;

Your query looks alright, but I don't think it will let you create a view if more than one column has the same name.
Since there are duplicates, e.g. CITY, I think the only way around it is to name all the columns and give unique names for duplicate columns.

Related

How to build a complex sql query?

Database design here
I want to get records from the product_spec_data table that are associated with products whose category_id is 5.
Please help me make a query to the database...
All of the relationship are clearly laid out, a simple join across tables would works.
SELECT psd.*
FROM product_spec_data psd
INNER JOIN product_spec_values psv ON psd.id = psv.product_spec_data_id
INNER JOIN products prod ON psv.product_id = prod.id
INNER JOIN categories cat ON prod.category_id = cat.id
-- with category id = 5
WHERE cat.id = 5;
I am not sure what do you mean by complex query. I guess your question is not complete. I think the query for your question (if it is T-SQL) will be as follows
select d.*
from product_spec_data d
left outer join product_spec_values v on d.id=v.product_spec_data_id
left outer join products p on v.product_id=p.id
where p.category_id=5
(I think in MySQL also above syntax will remain same, you may remove [outer] clause in MySQL)

Is it true that all joins following a left join in a SQL query must also be left joins? Why or why not?

I remember this rule of thumb from back in college that if you put a left join in a SQL query, then all subsequent joins in that query must also be left joins instead of inner joins, or else you'll get unexpected results. But I don't remember what those results are, so I'm wondering if maybe I'm misremembering something. Anyone able to back me up on this or refute it? Thanks! :)
For instance:
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id -- this inner join might be bad mojo
Not that they have to be. They should be (or perhaps a full join at the end). It is a safer way to write queries and express logic.
Your query is:
select *
from customer c left join
ledger l
on c.id = l.customerid inner join
order o
on l.orderid = o.id
The left join says "keep all customers, even if there is no matching record in ledger. The second says, "I have to have a matching ledger record". So, the inner join converts the first to an inner join.
Because you presumably want all customers, regardless of whether there is a match in the other two tables, you would use a left join:
select *
from customer c left join
ledger l
on c.id = l.customerid left join
order o
on l.orderid = o.id
You remember correctly some parts of it!
The thing is, when you chain join tables like this
select * from customer
left join ledger on customer.id= ledger.customerid
inner join order on ledger.orderid = order.id
The JOIN is executed sequentialy, so when customer left join ledger happens, you are making sure all joined keys from customer return (because it's a left join! and you placed customers to the left).
Next,
The results of the former JOIN are joined with order (using inner join), forcing the "the first join keys" to match (1 to 1) with the keys from order so you will end up only with records that were matched in order table as well
Bad mojo? it really depends on what you are trying to accomplish.
If you want to guarantee all records from customers return, you should keep "left joining" to it.
You can, however, make this a little more intuitive to understand (not necessarily a better way of writing SQL!) by writing:
SELECT * FROM
(
(SELECT * from customer) c
LEFT JOIN
(SELECT * from ledger) l
ON
c.id= l.customerid
) c_and_l
INNER JOIN (OR PERHAPS LEFT JOIN)
(SELECT * FROM order) as o
ON c_and_l.orderid (better use c_and_l.id as you want to refer to customerid from customers table) = o.id
So now you understand that c_and_l is created first, and then joined to order (you can imagine it as 2 tables are joining again)

SQL select for many to many relationship using binding table

I am struggling with writing a select for diagram on the picture.
What I want to do is write a select, which will show me details of a car repair. As you can see in table Repairs there are only 2 attributes but I am not sure if it's necessary to add more, especialy those from employees_list and parts_list, since I want to show repair data for every vehicle by it's plate_number. By repair data I mean repair id, vehicle plate_number, all employees working on the repair and all parts used on the repair. If my diagram is wrong, please help me fix it and I have no idea how to write select for this because of the many to many relation and the use of binding tables.
This is not so hard as it may seem.
First, obviously, we have to select cars:
select vehicles.* from vehicles
then, let's join repairs:
select
vehicles.*
from vehicles
inner join repairs on vehicles.id = repairs.vehicle.id
We don't need data from repairs in resule set, so we just join it but not mention in 'select' part.
Then we have to join parts needed for repair, and info about parts itself:
select
vehicles.*
from vehicles
inner join repairs on vehicles.id = repairs.vehicle.id
inner join parts_list on parts_list.repair_id = repairs.id
inner join parts on parts_list.part_id = parts.id
For that query we get amout of rows equivalent of amount of parts needed for repair. But it would be more easy to handle such data in code if we aggregate all of them into json column. So in result set we willsee something like:
vehicle_id, vehicle_part, parts_needed_as_json
Lets aggregate this:
select
vehicles.*, json_agg(parts.*) as parts_needed
from vehicles
inner join repairs on vehicles.id = repairs.vehicle_id
inner join parts_list on parts_list.repair_id = repairs.id
inner join parts on parts_list.part_id = parts.id
group by vehicles.id, repairs.id
Now you can add same logic for employees:
select
vehicles.*,
json_agg(parts.*) as parts_needed,
json_agg(employes.*) as employees_needed
from vehicles
inner join repairs on vehicles.id = repairs.vehicle.id
inner join parts_list on parts_list.repair_id = repairs.id
inner join parts on parts_list.part_id = parts.id
inner join employees_list on employes_list.repair_id = repairs.id
inner join employees on employees_list.employee_id = employees.id
group by vehicles.id, repairs.id
BTW, I suggest you to rename your tables to lowercase and singulars.
Like: 'repair', 'employee' and 'vehicle';
Also, name your binding tables like: 'repair_part' and 'repair_employee'.
Some people even suggest to arrange related tables in that names by alphabet, like: 'employee_repair' and 'part_repair', but I think it's not required;
Maybe this is a question of taste but in most cases this leads to more readable queries.
I.e, the query above will looks like:
select
vehicle.*,
json_agg(part.*) as parts_needed,
json_agg(employee.*) as employees_needed
from vehicle
inner join repair on vehicle.id = repair.vehicle_id
inner join parts_repair on parts_repair.repair_id = repair.id
inner join part on parts_repair.part_id = part.id
inner join employees_repair on employees_repair.repair_id = repair.id
inner join employee on employees_repair.employee_id = employee.id
group by vehicle.id, repair.id
Note how elegant 'on' conditions looks now: parts_repair.part_id = part.id, parts_repair.part_id = part.id
Sorry for bad english

What is wrong with my join in this query?

Im practicing basic SQL with this site http://www.sqlishard.com/Exercise
Here is the question:
S5.0 - INNER JOIN
Now that we can pull data out of a single table and qualify column
names, let's take it a step further. JOIN statements allow us to
'join' the rows of several tables together using a condition to define
how they match one another. SELECT [columns] FROM FirstTable INNER
JOIN SecondTable ON FirstTable.Id = SecondTable.FirstTableId
Try using the INNER JOIN syntax to SELECT all columns from the
Customers and Orders tables where the CustomerId column in Orders
matches the Id column in Customers. Since both tables have an Id
column, you will need to qualify the Customers id in the WHERE clause
with either the table name or a table alias.
Here is my answer:
SELECT *
FROM Customers AS c
INNER JOIN Orders AS o ON c.ID = o.ID
WHERE o.CustomerID = c.ID
The site says im wrong? Could anyone explain where i'm going wrong?
EDIT: I see now I dont need the WHERE clause, but the question states..
you will need to qualify the Customers id in the WHERE clause with
either the table name or a table alias.
Hence my confusion. Thanks none the less.
Try this way:
SELECT c.ID,o.ID
FROM Customers AS c
INNER JOIN Orders AS o ON o.CustomerID = c.ID
or using where clause
SELECT *
FROM Customers AS c, Orders AS o
where o.CustomerID = c.ID
If you use JOIN.. ON, you do not need where clause

Selecting Data from 2 tables based on another

I am using Oracle via the SQL+ command line, i'm trying to display data from two different tables, but i require the use of a third table to determine what to display. Below is an image of my sample 3 tables.
Stack won't let me show my images in the question so here is a link:
I want to display the "Name","O_ID" and "Date" for each order. I'm quite new to SQL and this may have been answered before but i could not find it.
JOIN the tables:
SELECT
c.Name,
o.O_ID,
od.Date
FROM Customer AS c
INNER JOIN "Order" AS o ON c.C_ID = o.C_ID
INNER JOIN OrderDate AS od ON o.O_ID = od.O_ID;
What you are attempting to do is a very common practice and requires a INNER JOIN.
From a design perspective, the Order Date table shouldn't even exist. The date column should just reside within the Order table. I wrote the query based on that design:
SELECT
o.O_ID,
o.Date,
c.Name,
FROM
customer AS c
INNER JOIN order AS o ON c.C_ID = o.C_ID
Edit:
More on the issue of your design: A natural ordering of your data would be that there is 1 date for an order, not many dates for an order. Introducing another table to simply store the date allows for there to potentially be many dates associated with an order, which is simply unnatural.
Do a JOIN
select c.Name, o.O_ID, od.Date
from Customer c
inner join Order o on o.O_ID = c.C_ID
inner join OrderDate od on o.O_ID = od_ID
Doc: http://www.w3schools.com/sql/sql_join.asp