//Personal understanding, not a hw assignment
So in the sample db northwind from MS there are the tables: orders o, [order details] od, customers c
o has orderID, customerID (inc. duplicates)
od has orderID (inc. duplicates), unitprice, quantity, discount
c has customerID, companyName
roughly speaking,
I want to join on
o.customerID = c.customerID; selecting companyName ///
join on o.orderID = od.orderID; selecting unitprice, quantity, discount
my end goal is to
sum(q (up - d)) AS 'Order Total' group by od.orderID then
sum(Order Total) group by companyName(?)
My main issue is not know how/what to join properly though.
Thanks in advance
Check out your scenario on SQL Fiddle
SELECT comp.`company_name` AS 'company',COUNT(DISTINCT o.id_sales_order) AS 'total_orders',SUM(`unit_price`) AS 'grand_total'
FROM sales_order AS o
LEFT JOIN sales_order_item AS od ON od.fk_sales_order = o.id_sales_order
LEFT JOIN customer AS c ON c.id_customer = o.fk_customer
LEFT JOIN company AS comp ON comp.id_company = c.fk_company_id
GROUP BY comp.`company_name`
hope this what you are looking for
Assuming that you create the correct Select statement as you required, the join part should be something like:
From Orders o join Order_Detail od on o.orderID = od.orderID
join Customer c on o.customerID = c.customerID
Types of join can be: join, inner join, right/left join. It depends on you what do you want to achive i.e if you want to exclude/include null references. But the structure is the same.
Related
Is there a way to answer this question without using joins?
Write a query that finds, for each customer X, another customer Y who has ordered at least one product in common with X. Find all such pairs of Customers (X, Y) and against each pair, the number of overlapping products. The query should thus have three columns. Order the results by the number of overlapping products.
The question uses the https://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
database.
Using joins, I can answer the question like this:
O2.CustomerID AS Cust2,
COUNT(*) AS OverlappingProd
FROM (SELECT O.CustomerID, OD.ProductID
FROM Orders AS O
JOIN OrderDetails AS OD
ON OD.orderid = o.orderid) AS O1
JOIN(SELECT O.CustomerID, OD.ProductID
FROM Orders AS O
JOIN OrderDetails AS OD
ON OD.orderid = o.orderid) AS O2
ON O2.ProductID = O1.ProductID
AND O2.CustomerID > O1.CustomerID
GROUP BY
O1.CustomerID,
O2.CustomerID
ORDER BY COUNT(*) DESC;
Is there a way to answer it not using the JOIN function? Thank you for your time and consideration.
I cannot think of a way of doing this without any joins. You can express this in SQL using cross join and exists, so the following comes close:
select c1.customerid, c2.customerid,
(select count(*)
from products p
where exists (select 1
from orderdetails od
where od.productid = p.productid and
exists (select 1
from orders o
where o.orderid = od.orderid and
o.customerid = c1.customerid
)
) and
exists (select 1
from orderdetails od
where od.productid = p.productid and
exists (select 1
from orders o
where o.orderid = od.orderid and
o.customerid = c2.customerid
)
)
) as num_products
from customers c1 cross join
customers c2
where c1.customerid < c2.customerid;
Although this syntax will work in many databases, the nested correlation clauses are not supported in MySQL. So, even accepting the CROSS JOIN, this does not work in MySQL.
The reason why a JOIN seems necessary is to get two independent customer ids in the result set.
SELECT
ORDER_ITEM.OrderID,
ORDERS.OrderDate
FROM ORDER_ITEM LEFT JOIN ORDERS
ON ORDER_ITEM.OrderID = ORDERS.OrderID
LEFT JOIN PEOPLE
ON ORDERS.CustomerID = PEOPLE.PeopleId AND ORDERS.EmployeeID = PEOPLE.PeopleId
where PEOPLE.FirstName + PEOPLE.LastName = 'April Roberts'
My results are outputting 0 rows. Not sure what I am doing wrong here.
Make sure you have data in the table that match your criteria. e.g. You have orders by the person with the name April Roberts. If you use LEFT JOIN, the query will return all results despite if you do not have any order by the person. So, INNER JOIN or simply JOIN is fine if you ONLY want orders that associates with the person.
SELECT oi.OrderID, o.OrderDate
FROM ORDER_ITEM oi
JOIN ORDERS o ON oi.OrderID = o.OrderID
JOIN PEOPLE p ON o.CustomerID = p.PeopleId
WHERE p.FirstName = 'April' AND p.LastName = 'Roberts'
This should work better for the search (you are using a space that doesn't exist)
SELECT OI.OrderID, O.OrderDate
FROM ORDER_ITEM OI
LEFT JOIN ORDERS O ON OI.OrderID = O.OrderID
LEFT JOIN PEOPLE P ON O.CustomerID = P.PeopleId AND O.EmployeeID = P.PeopleId
WHERE P.FirstName='April' AND P.LastName = 'Roberts';
However, logically, CustomerID and EmployeeID can't match the same employee. You'd need a second link to people
SELECT OI.OrderID, O.OrderDate
FROM ORDER_ITEM OI
LEFT JOIN ORDERS O ON OI.OrderID = O.OrderID
LEFT JOIN PEOPLE P ON O.CustomerID = P.PeopleId
LEFT JOIN PEOPLE E ON O.EmployeeID = E.PeopleId
WHERE P.FirstName='April' AND P.LastName = 'Roberts';
Your error is that you want the people record match employee and customer of the same order, but the customer will never equal the employee of course.
Is April Roberts the customer or the employee? Decide and then select the data from the orders table for that customer or employee:
select orderid, orderdate
from orders
where customerid in
(
select peopleid
from people
where firstname = 'April'
and lastname = 'Roberts'
);
No need to join the order_item table. No need to join at all. Only join when you want joined data.
I am using IN for the case there exist two April Roberts. If there is a constraint on the table preventing that, then you can change IN to =.
If you were really interested in the orders linked to some April Roberts, not knowing whether she is employee or customer, you'd use EXISTS instead:
select orderid, orderdate
from orders o
where exists
(
select *
from people p
where p.firstname = 'April'
and p.lastname = 'Roberts'
and p.peopleid in (o.customerid, o.employeeid)
);
There is another error in your query by the way:
where PEOPLE.FirstName + PEOPLE.LastName = 'April Roberts'
You are adding two values here (+ is for numeric addition), so MySQL converts the strings FirstName and LastName to numbers. Such conversion from a string that starts with a letter results in the value zero in MySQL, so you have where 0 + 0 = 0 which is always true. If + would do string concatenation as you obviously supposed (which is the || operator in standard SQL and the CONCAT function in MySQL), then you'd probably have gotten where 'AprilRoberts' = 'April Roberts' which would always be false.
I am new to SQL and have the following task I'm trying to complete:
I need to create a query that will return a set of results based on a set of dates. Here are my TABLES/columns:
Order Line
order_id,
line_no,
qty_shipped,
total_shipped_qty,
part_id,
part_description,
desired_ship_date,
ship_date,
customer_id
Shipper
packlist,
order_id
Customer
name,
customer_id
Customer Order
PO,
order_id
I need my output to look like this:
packlist,
order_id,
line_no,
total_shipped_qty,
part_id,
part_description,
name,
po,
desired_ship_date,
ship_date,
So far I have come up with a query below that gets me all the column data I need from the Order Line Table based on a set of dates. I'm having trouble joining the other tables together to get the rest of the columns I need in my output. Specifically packlist, po, and name from their tables. I need to run this query first:
SELECT ORDER_ID,
LINE_NO,
TOTAL_SHIPPED_QTY,
PART_DESCRIPTION,
DESIRED_SHIP_DATE,
SHIP_DATE,
TOTAL_SHIPPED_QTY
FROM ORDER_LINE
WHERE [SHIP_DATE] BETWEEN 'XXXX/XX/XX' AND 'XXXX/XX/XX'
Based on the results above I need to pull in the rest of the data from the other tables. Any help is greatly appreciated. Thank you
SELECT s.packlist, o.Order_ID,
o.total_shipped_qty,o.Part_ID, o.Part_Description, co.PO,
c.Name, o.Desired_Ship_Date, o.Ship_Date
from OrderLine o
inner join Customers c on c.Customer_ID = o.Customer_ID
inner join Shipper s on s.Order_ID = o.Order_ID
inner join CustomerOrders co on co.Order_ID = o.Order_ID
WHERE o.[SHIP_DATE] BETWEEN 'XXXX/XX/XX' AND 'XXXX/XX/XX'
I don't think you need to join on CustomerOrders at this point.
Just a INNER JOIN between all the tables is what you need
SELECT S.PACKLIST,
O.ORDER_ID,
O.TOTAL_SHIPPED_QTY,
O.PART_ID,
O.PART_DESCRIPTION,
C.NAME,
CO.PO,
O.DESIRED_SHIP_DATE,
O.SHIP_DATE
FROM ORDERLINE O
JOIN CUSTOMERS C
ON C.CUSTOMER_ID = O.CUSTOMER_ID
JOIN SHIPPER S
ON S.ORDER_ID = O.ORDER_ID
JOIN CUSTOMERORDER CO
ON CO.ORDER_ID = O.ORDER_ID
WHERE O.[SHIP_DATE] BETWEEN 'XXXX/XX/XX' AND 'XXXX/XX/XX'
Hey guys I have an question that I need some support on.
I am trying to get the top 3 suppliers with a single query from a table.
This is the original question: Who are the top three suppliers by revenue, and where are they located?
Here is the online table and a query you have to run to create a new table.
http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
CREATE TABLE ByCustomerOrders AS
SELECT
o.OrderID
, p.ProductName
, p.ProductID
, Price
, Quantity
, Price * Quantity AS subtotal
, c.CustomerID
, s.SupplierID
FROM OrderDetails AS od
LEFT JOIN Orders AS o ON od.OrderID = o.OrderID
LEFT JOIN Products AS p ON p.ProductID = od.ProductID
LEFT JOIN Customers AS c on c.CustomerID = o.CustomerID
LEFT JOIN Suppliers AS s ON s.SupplierID = p.SupplierID;
From that, it creates a new table I need to list just the top 3 suppliers, pretty much the supplierID row value that shows up the most.
Some help would be appreciated.
If you want to get the 3 top suppliers by revenue (and revenue is the sum of all subtotals) this should work:
SELECT s.*, SUM(co.subtotal) as revenue
FROM ByCustomerOrders co
INNER JOIN Suppliers s ON co.SupplierID = s.SupplierID
GROUP BY co.SupplierID
ORDER BY revenue DESC
LIMIT 3;
PS: You should consider using decimal (instead of float or double) for columns that will represent money or you'll get precision errors and your numbers won't add up.
You have a fairly complex schema that you haven't completely disclosed, so this is a guess.
SELECT COUNT(s.SupplierID) AS supplier_count,
SUM(Price * Quantity) AS supplier_subtotal,
s.SupplierID,
s.SupplierName /*this is a guess*/
FROM OrderDetails AS od
LEFT JOIN Orders AS o ON od.OrderID = o.OrderID
LEFT JOIN Products AS p ON p.ProductID = od.ProductID
LEFT JOIN Customers AS c on c.CustomerID = o.CustomerID
LEFT JOIN Suppliers AS s ON s.SupplierID = p.SupplierID
GROUP BY s.SupplierID, s.SupplierName
ORDER BY COUNT(s.SupplierID) DESC
LIMIT 3
This should give you the top suppliers (by units ordered).
The trick here is to use an aggregate query (SUM() ... GROUP BY) and then order by one of the aggregate values with a DESCending qualifier.
You might want to troubleshoot this query by leaving off the LIMIT clause until you're sure you're getting the right information.
I have the folowing tables.
ORDER
OrderNumber
CustomerNumber
EmployeeNumber
OrderDate
CUSTOMER
CustomerNumber
Name
Address
EMPLOYEE
EmployeeNumber
Name
Address
ORDERDETAIL
OrderNumber
Qty
Description
Price
Let say ORDERDETAIL table has 10 records
I would like to write a query that will return 10 records from ORDERDETAIL table to include Employee name, employee address, customer name, customer address and and order Date.
I know that I could write a query and use INNER JOIN to get the info from ORDER table, but how do you create the rest of query to get the info from the CUSTOMER and EMPLOYEE tables.
SELECT *
FROM OrderDetail D
INNER JOIN Order O
ON D.OrderNumber = O.OrderNumber;
Just add some more joins...
SELECT *
FROM OrderDetail D
JOIN Order USING (OrderNumber)
JOIN Customer USING (CustomerNumber)
JOIN Employee USING (EmployeeNumber)
You might want to re-order the JOINs in order to have the smallest tables first, as this could provide you with some performance boost (depending on your server's version, the most recent will optimize the join for you and might actually execute the joins in the "probably best" way).
Also, in the MySQL dialect at least, JOIN implicitly expands to INNER JOIN, and writing
A JOIN B USING (COL)
is equivalent to writing
A JOIN B ON (A.COL = B.COL)
SELECT *
FROM OrderDetail D
INNER JOIN Order O ON D.OrderNumber = O.OrderNumber
INNER JOIN Eployee E on O.EployeeNumber = E.EployeeNumber
INNER JOIN Customer C on O.CustomerNumber = C.CustomerNumber
if you have foreign key reference between
ORDER.EmployeeNumber and EMPLOYEE.EmployeeNumber
ORDER.CustomerNumber and CUSTOMER.CustomerNumber
then try this
SELECT
E.name AS employeeName,
E.Address AS employeeAddress,
C.name AS customerName,
C.Address AS customerAddress.
O.OrderDate
FROM OrderDetail D
INNER JOIN Order O ON D.OrderNumber = O.OrderNumber
INNER JOIN EMPLOYEE E ON E.EmployeeNumber = 0.EmployeeNumber
INNER JOIN CUSTOMER C ON C.CustomerNumber= 0.CustomerNumber
LIMIT 0,10