How do I build a query that crosses multiple tables? - sql-server

Here are my tables:
CUSTOMER
Cust_ID (PK)
Name
ORDERS
Order_ID (PK)
Cust_ID (FK)
ORDER_LINE
Order_ID (pk)
Part_ID (FK)
PART
Part_ID (PK)
Part_Description
Now I want to list the customer details, the part number and the description of the parts that each customer ordered.
How do i do this?
Thanks.

You should use "JOIN" using the FK, but from what I see you don't have a foreign key between "ORDERS" and "ORDER_LINE". Are you sure you're not missing something from the table definition, ie: ORDER_LINE should maybe have the ORDER_ID as a FK ?
Hope this helps

You can try something like
SELECT c.*,
p.*
FROM CUSTOMER c INNER JOIN
ORDERS o ON c.Cust_ID = o.Cust_ID INNER JOIN
ORDER_LINE ol ON o.Order_ID = ol.Order_Number INNER JOIN
PART p ON ol.Part_Number = p.Part_Number
Have a look at
Join (SQL)
An SQL join clause combines records from two or more tables in a
database.
SQL Joins
The JOIN keyword is used in an SQL statement to query data from two or
more tables, based on a relationship between certain columns in these
tables.
And for some graphic examples
JOIN Basics

What you need is a simple straightforward JOIN like so:
SELECT
c.Cust_ID,
c.Name,
l.Part_Number,
l.Part_Description
FROM CUSTOMER c
INNER JOIN ORDERS o ON c.Cust_ID = o.Cust_ID
INNER JOIN ORDER_LINE ol ON o.OrdeR_ID = ol.Order_Number
INNER JOIN PART l ON ol.Part_Number = l.Part_Number

You want an SQL "join", such as:
SELECT c.Name, ol.Part_Number, p.Part_Description
FROM Customer AS c
JOIN Orders AS o ON c.Cust_ID = o.Cust_ID
JOIN Order_Line AS ol ON o.Order_ID = ol.Order_Number
JOIN Part AS p ON ol.Part_Number = p.Part_Number
Be aware that without a WHERE clause, this query will return all all parts in all orders for all customers, which will really hammer the network and perform poorly on anything but a tiny database:
WHERE (c.Cust_ID = MyCustomerID)
MySQL join syntax
SQL Server join syntax

Related

DB Schema Taxonomy for species : conditional joins or redesign?

I need some advice to design a DB Schema. I am working on a project where I need to classify species.
All species belong to a gender, a family, an order, a class, a branch and finaly a kingdom.
But some of them have a subBranch between class and branch. I first gave the species entity a FK pointing to each single taxonomy.
Then I thought about only giving the species entity the "gender FK" and go all the way up from there to get its full taxonomy. It seemed to work but I realised I could not retreive the subBranch for species concerned by it.
In the class entity I have two FK, one for subBranch and one for branch. Depending on the species, the branchId FK exists in the class entity (and then the subBranch FK is null) leading to Branch and then Kingdom. Or the subBranch FK exists and leads to the SubBranch then from there to Branch and finally kindgom.
In SQL, I have something like this for the species view (I commented in english where I am stuck):
SELECT
S.*,
G.LatinName as 'GenderLatinName',
G.Name as 'GenderName',
F.LatinName as 'FamilyLatinName',
F.Name as 'FamilyName',
O.LatinName as 'OrderLatinName',
O.Name as 'OrderName',
C.LatinName as 'ClassLatinName',
C.Name as 'ClassName',
Sb.LatinName as 'SubBranchLatinName',
Sb.Name as 'SubBranchName',
B.LatinName as 'BranchLatinName',
B.Name as 'BranchName',
K.LatinName as 'KingdomLatinName',
K.Name as 'KingdomName'
from Species S
join Gender G on G.Id = S.GenderId
join Family F on F.Id = G.FamilyId
join [Order] O on O.Id = F.OrderId
join Class C on C.Id = O.ClassId
--if class entity has an existing SubBranchId then join SubBranch to it and then the Branch to the SubBranch
-- if C.SubBranchId is not null
-- then join SubBranch on Sb.BranchId on C.BranchId
-- then join Branch on B.Id on Sb.BranchId
--if class entity has no SubBranchId then straightaway join Branch to it
-- else
-- join Branch on B.Id on C.BranchId
join Branch B on B.Id = C.BranchId
join Kingdom K on K.Id = B.KingdomId
I have seen some questions on conditional joins but I could not get it work. I thought about the UNION ALL but the number of columns vary between the two queries as one has an additional field.
Perhaps the schema design needs to be changed.
How could I do?
Your schema is generally fine, apart from 2 rather minor notes:
In taxonomy, it's usually called "Genus", not "Gender";
I strongly suggest to come up with some other name for the Order table. Trust me, if you will have to write any amount of code worth mentioning against a schema like that, you'll curse the day you chose the table name to be the same as this particular reserved keyword. Orders, Order_, OrderT (from "Taxonomy") - anything will do.
As such, the query should be quite simple:
select s.*,
-- Other columns
isnull(sb.LatinName, '(No sub-branch)') as [SubBranchLatinName],
-- The rest of stuff
from Species S
inner join Genus G on G.Id = S.GenusId
inner join Family F on F.Id = G.FamilyId
inner join OrderT O on O.Id = F.OrderId
inner join Class C on C.Id = O.ClassId
inner join Branch B on B.Id = C.BranchId
left join dbo.SubBranch sb on sb.BranchId = b.Id and sb.Id = c.SubBranchId
inner join Kingdom K on K.Id = B.KingdomId
Left join allows you to bring in the table which might contain no rows that match the condition, without losing these rows in the final output.
I think that having a star schema i.e. SPECIES table contain FKs to each taxonomy table would be faster for selects. This will also remove complications of conditional joins and any other logical "anomalies".
If you want to stick with a chain, then there are two ways:
Conditional join:
Example Below
from Species S
join Gender G on G.Id = S.GenderId
join Family F on F.Id = G.FamilyId
join [Order] O on O.Id = F.OrderId
join Class C on C.Id = O.ClassId
LEFT JOIN SubBranch AS SB ON .....
INNER JOIN Branch AS B ON SB.BranchID = B.Id OR C.BranchID = B.Id
This will be slow.
UNION ALL approach would probably be faster. To work around number of columns differences, you will need to add NULL and/or empty string constants in place of SubBranch columns for the query without SubBranch.
Another way is to add a dummy sub branch records for classes without a sub branch. This way there is always a record in SubBranch table, and you do not need conditional joins. I recommend this solution.

SQL Join using multiple tables

I'm using the version of SQL Server which comes with Visual Studio 2017 and trying to create a view by joining columns from four tables which are as follows:
Table1: Employee (EmpID, EmpName, EmpContact, EmpSalary)
Table2: Customer (CustID, CustName, CustContact, CustEmail)
Table3: Orders (OrderID, OrderCustID, OrderDate, OrderStatus, OrderValue)
Orders.OrderCustID is foreign key which relates to Customer.CustID
Table4: Job (JobID, JobOrderID, JobEmpID, JobStatus, JobRemarks)
Job.JobOrderID and Job.JobEmpID are two foreign keys which relate to Orders.OrderID and Employee.EmpID respectively.
Now, I want to perform a join which will show all records of Orders table along with matches from other tables in following order:
OrderID, JobStatus, OrderStatus, CustID, CustName, CustContact, CustDue, EmpID, EmpName, EmpContact, Oredrvalue
Someone please help me write the SQL Query to perform the join. Many thanks in advance.
You need to walk through each JOIN to figure out what to join where. In other words, how do you get from Employees to Customers? It's just a logical walk-through.
Here's one approach, using inner joins (basically a big intersection of sets).
SELECT OrderID, JobStatus, OrderStatus, CustID, CustName, CustContact, CustDue, EmpID, EmpName, EmpContact, OrderValue
FROM Job
INNER JOIN Orders
ON Orders.OrderId=Job.JobOrderID
INNER JOIN Customer
ON Customer.CustId=Orders.OrderCustId
INNER JOIN Employee
ON Employee.EmpId=Job.JobEmpID
OK, I figured it out and I'm posting it here for any future reference.
SELECT o.OrderID, j.JobStatus, o.OrderStatus, c.CustID, c.CustName, c.CustContact, c.CustDue, e.EmpID, e.EmpName, e.EmpContact, o.Oredrvalue
FROM Orders o
LEFT JOIN Customer c
ON o.OrderCustID=c.CustID
LEFT JOIN Job j
ON o.OrderID=j.JobOrderID
LEFT JOIN Employee e
ON j.JobEmpID=e.EmpID
I performed left join on all occasions because I need all the records from Orders table. Thanks a lot to all who responded.

I want to select from two tables (a,b) which are related to each other through third table(c), but table a has a composite primary key

I want to select from two tables (customers,machins) which are related to each other through third table(orders), but table a has a composite primary key
Table customers has primary key as
id
Table machins has a composite primary key with these two columns:
machinId
machineModel
And these two are related to table orders
Id(fk)
machine(fk)
machintype
I want to select from customers and machins all machines that a person has bought (orders)
My select command is
Select c.name, c.land, m.namemachin
from orders o
inner join customers c on c.id = o.id
inner join machins m on o.machine = m.Id
where c.name = 'karl' and m.machine = o.machintype
But it doesn't work
Can you please help me?
If you have a composite primary key in table machins then both of that column should be available in table orders for a proper relation. Then only you can do a proper join this tables for a select query.
As per the discussion m.machineModel = o.machintype
So please try this query
Select c.name, c.land, m.namemachin
from orders o
inner join customers c on c.id = o.id
inner join machins m on m.machinId = o.machine
and m.machineModel = o.machintype
where c.name = 'karl'
If your fetching is something related to string concatenation i.e to obtain all machines as string. I think you can use STUFF and FOR XML PATH.
Or else go through th below link it might help
http://www.w3resource.com/sql/joins/using-a-where-cluase-to-join-two-tables-related-by-a-composite-primary-key-or-foriegn-key-pair.php

Complex SQL Join

I am fairly new to SQL joins, but I have a tricky issue here. I have tried to resolve this on my own, and searched as well, but unsuccessful.
I have two primary SQL tables
CustProfile
ClientID || ClientName
CustTransaction
CorpID || DivID || DeptID
I need to display my output as follows:
`CorpID` `CorpIDClientName` `DivID` `DivIDName` `DeptID` `DeptIDName`
CustTransaction.CorpID join on CustProfile.ClientID to get `CorpIDClientName`
CustTransaction.DivID join on CustProfile.ClientID to get `DivIDName`
CustTransaction.DeptID join on CustProfile.ClientID to get `DeptIDName`
I hope someone can provide the join query. Thanks in advance
try this one:
SELECT a.CorpID,
b.ClientName AS CorpIDClientName,
a.DivID,
c.ClientName AS DivIDName,
a.DeptID,
d.ClientName AS DeptIDName
FROM CustTransaction a
INNER JOIN CustProfile b
on a.CorpID = b.ClientID
INNER JOIN CustProfile c
on a.DivID = c.ClientID
INNER JOIN CustProfile d
on a.DeptID = d.ClientID
Am I understanding correctly? You have Corporations, Divisions, and Departments all stored within the CustProfile table together.
So you are only joining the 2 different tables, but you need to join those 2 tables 3 separate times to get each of the different types of customer (Corp or Div or Dept)
If that's the case, what you need to do is alias the table that you are including multiple times so you can join it as if it were 3 separate tables, one for corps, one for divisions, and one for departments.
I'm not sure if the syntax would be the same in MSSQL, but for most SQL databases your join query would look something like this:
SELECT corps.ClientID CorpID, corps.ClientName CorpIDClientName,
divs.ClientID DivID, divs.ClientName DivIDName,
depts.ClientID DeptID, depts.ClientName DeptIDName
FROM CustProfile corps, CustProfile divs, CustProfile depts, CustTransaction t
WHERE t.CorpID = corps.ClientID
AND t.DivID = divs.ClientID
AND t.DeptID = depts.ClientID
That should, I think, more or less do what you want...

Need help creating a query for a non-normalized database

I've never worked with a non-normalized database before, so I'll try and explain my problem as best I can. So I have two tables:
The customers table holds all the customers information, and the orders table holds all the orders that they have placed. I haven't listed all the fields in the tables, just the ones that I need. The customer number in both tables is not the primary key, but I'm inner joining on them anyway. So the problem I'm having is that I don't know how to make a query that:
Selects all the customers with their first name, last name, and email, and also show the most recent orderdate, most recent total, and most recent ordertype. I know that I have to use a max() aggregate for the date, but that's as far as I got. Please help a noob out.
You can try:
SELECT FirstName,
LastName,
Email,
OrderDate,
OrderTotal,
OrderType
FROM Customers AS C
INNER JOIN Order AS O
ON O.CustomerNumber = C.CustomerNumber AND
O.OrderDate = (
SELECT MAX (O1.OrderDate)
FROM Order AS O1
WHERE O1.CustomerNumber = C.CustomerNumber)
)
assuming that Orders.OrderDate is unique for each CustomerNumber, does this work for you? if a single CustomerNumber has more than one entry in Order for OrderDate, you'll get each of those rows.
select c.FirstName, c.LastName, c.Email, o.OrderDate, o.OrderTotal, o.OrderType
from Customers c
join
(select CusomterNumber, max(OrderDate) as MostRecentOrderDate
from Orders
group by CustomerNumber
) mro on mro.CustomerNumber=s.CustomerNumber
join Orders o on o.OrderDate=mro.MostRecentOrdeDate and
o.CustomerNumber=mro.CustomerNumber
Try this:
SELECT
Customers.*, Orders.*
FROM
Customers
JOIN
(SELECT
Customer_Number,
MAX(Order_Date) OrderDate
FROM
Orders
GROUP BY
Customer_Number
) as Ord ON Customers.Customer_Number = Ord.Customer_Number
JOIN Order ON Orders.Customer_Number = Ord.Customer_Number
If you are doing this with SQL Server use the query designer and basically all you want to do is do a join since you have two keys that are the same one in Customer Table ->Customer Join on Order->Customer alias the Customer table as C and Orders table as O
so for example
SELECT Customer.*, Orders.*
From Customer c, Orders O INNER JOIN O where C.Customer Number = O.Customer Number
This should be enough to get you started.. if you don't want all the fields then fully qualify the names for example
SELECT C.FirstName, C.LastName, O.OrderDate, O.OrderType FROM Customer C, Orders O
WHERE C.Customer NUmber = O.Customer Number //this is another way of doing a Join when working with the where Clause.

Resources