Getting info through 3 tables - mysql

I'm following the SQL tutorial from w3schools.
I want to get the value of all orders delivered by a shipper. I don't have any idea about how I can get these details as the info are in different tables and the INNER JOIN didn't worked for me.
Database: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_groupby
By now, I managed to get the number of orders by each shipper.
SELECT Shippers.ShipperName,COUNT(Orders.OrderID) AS NumberOfOrders FROM Orders
LEFT JOIN Shippers
ON Orders.ShipperID=Shippers.ShipperID
GROUP BY ShipperName;
How could I get the value of those?

To bring the Price of a Product into your query you will need to join in tables OrderDetails to the Order table on the Orders.Id and then join in the Products table to the OrderDetail table on ProductID
SELECT Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
Sum(Products.price * OrderDetails.Quantity) AS SumOfPrice
FROM Orders
LEFT JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
LEFT JOIN OrderDetails ON ORders.OrderID = OrderDetails.OrderID
LEFT JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY ShipperName;
I just stuck with LEFT JOIN here as your example used, but an INNER JOIN would work just as well and be more efficient.
The FROM clause of the SQL statement is one of the first parts of the SQL to run against your database. It establishes which tables we are grabbing information from and the relationship between those tables (using the ON keyword). So here we bring in 4 tables, and use the ON keyword to show the relationship between all of them using their respective IDs. Then we can add their fields to the SELECT portion of the SQL statement and aggregate where needed.

If you want the "sum" of the product prices, that would be very similar to what you already have. Note how you currently use the COUNT() function to get the count, you can use the SUM() function to get the total of any numeric column.
Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
Or perhaps the price also needs to be multiplied by the quantity in this calculation? Something like this:
SELECT
Shippers.ShipperName,
COUNT(Orders.OrderID) AS NumberOfOrders,
SUM(Products.Price * OrderDetails.Quantity) AS PriceOfOrders
FROM
Orders
INNER JOIN Shippers ON Orders.ShipperID = Shippers.ShipperID
INNER JOIN OrderDetails ON Orders.OrderID = OrderDetails.OrderID
INNER JOIN Products ON OrderDetails.ProductID = Products.ProductID
GROUP BY
ShipperName
It's up to your understanding of the table structure and the data, really. But the concept is the same, grouping by a value and applying a calculation to the grouped values (count or sum).

Related

Query returns false information on column

If you run this:
SELECT o.orderid,suppliername,p.productname
FROM Suppliers s
JOIN Orders o
ON o.shipperid = s.supplierid
JOIN OrderDetails od
ON od.orderid = o.orderid
JOIN Products p
ON p.productid = od.productid
On https://www.w3schools.com/sql/trymysql.asp?filename=trysql_func_mysql_count
You get resuls where for each order-id, there is a set of rows with productnames and suppliernames.
Now, the funny thing is that for each Order as a whole (say a set of two rows for order 10300)
there is always the SAME suppliername.
But this isnt true. When you look up the table "products" you will find that for example for the products with ID 66 and 68, which are the products contained in order 10300, there are two different supplier IDs registered. 2 and 8.
And these resolve to two different suppliernames on the supplieres table.
Why is that? This is a fairly simple query in my opinion, I didnt expect to run into any issues with it. But here, the data presented to me in the tables and the data returned by the query clearly diverge.
Am I missing something or is their site/DB just broken?
The error is caused by the way you are joining to the Suppliers table. Instead of joining the Suppliers table to the Orders table, it seems like you want to join the Products to the Suppliers tables to get the suppliers for those products. Such a query would look like:
SELECT o.orderid, s.suppliername, p.productname
FROM Orders o
JOIN OrderDetails od ON od.orderid = o.orderid
JOIN Products p ON p.productid = od.productid
JOIN Suppliers s ON s.supplierid = p.supplierid

How to count from a single table whilst performing multiple joins

I was asked the following question:
Find the 3 vendors that supply our most famous products by number of units sold, not number of units ordered. Rank them first to third.
The database used is the online classicmodels db: http://mysqltutorial.org//tryit/
This is what I have done, I cannot seem to count the payments only and group by vendors. The count I get back is a product of all the joins.
SELECT p.productvendor FROM products AS p
INNER JOIN orderdetails AS od ON p.productcode = od.productcode
INNER JOIN orders AS o ON o.ordernumber = od.ordernumber
INNER JOIN customers AS c ON c.customernumber = o.customernumber
INNER JOIN payments AS py ON py.customernumber = c.customernumber
GROUP BY p.productvendor
ORDER BY COUNT(p.productvendor) DESC
LIMIT 3
Try to break the problem into smaller queries and then try to optimize the joins.
select count(p.productvendor) as product_count, p.productvendor from (JOINS) group by p.productvendor
-- this should give count by vendor. you can use sum(orderdetails.qty) also in case you
So the problem is reduced to be in the JOINS
JOINS ( has to be a collection of individual product sales)

is it possible to UNION and INNER JOIN for sql

im using the w3schools sql database to learn and i have come across a question.
is it possible to sort the results according to CustomerName after i have done a INNER JOIN?
this is the INNER JOIN statement
SELECT Orders.OrderID, Customers.CustomerName, Customers.ContactName
FROM Orders
INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID;
The UNION command in SQL is used to combine the results of your first query with the entire results of a second query that has the same columns. It is not used for ordering the first query. With your INNER JOIN you can sort the results just by adding ORDER BY:
SELECT Orders.OrderID, Customers.CustomerName, Customers.ContactName
FROM Orders
INNER JOIN Customers ON Orders.CustomerID = Customers.CustomerID
ORDER BY Customers.CustomerName;

MySQL error code 1242

I'm trying to create a view of some columns from 3 different tables. One of the columns 'OrderNumber' is in 2 of the tables so I'm trying to do a UNION for them, but because I've made a subquery it returns an 1242 error and won't return more than 1 row. I just want to know how I can rewrite this query so that there are no subqueries, or is there someway to bypass it. Or perhaps I need to write multiple queries? Though I'd prefer to keep it to the one query, thanks.
CREATE VIEW CustOrderItems AS
SELECT CustFirstName,
CustLastName,
(SELECT OrderNumber
FROM Orders
UNION
SELECT OrderNumber
FROM Order_Details)
OrderDate,
ShipDate,
QuantityOrdered * QuotedPrice as ItemTotal
FROM Customers JOIN Orders JOIN Order_Details;
Substitute whatever your customer id
drop view if exists custorders;
create view custorders as
SELECT c.CustFirstName,
c.CustLastName,
o.OrderNumber order_ordernumber,
od.OrderNumber orderdetails_ordernumber,
o.OrderDate,
o.ShipDate,
od.QuantityOrdered * od.QuotedPrice as ItemTotal
FROM Customers c
JOIN Orders o on c.id = o.cust_id
JOIN Order_Details od on o.ordernumber = od.ordernumber
where c.id = ?
It's not clear what are your join criteria because the statement syntax is bad. But I assume you want to join on OrderNumber like SELECT ... FROM Customers INNER JOIN Orders ON Customers.OrderNumber = Orders.OrderNumber. In this case, if you want to use order numbers from two tables just repeat the query and make union of the two like:
SELECT ,,, FROM Customers INNER JOIN Order_Details ON Customers.OrderNumber = Order_Details.OrderNumber
UNION
SELECT FROM Customers INNER JOIN Orders ON Customers.OrderNumber = Orders.OrderNumber

SQL ambigutiy when trying to display

Consider the following query i tried, there two tables, Orders and Customers, each have column name CustomerID, when i try to display both CustomerID's only one column is displaying, i can't understand why is it so, or am i understanding the basics wrong.
SELECT Customers.CustomerID,Orders.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
When i try to display only one column it is displaying well and good
SELECT Customers.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
and
SELECT Customers.CustomerID
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
So my problem is why I cant display the both.
use alias
SELECT Customers.CustomerID as customerid,Orders.CustomerID as ocustomerid
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
You need to define an alias for each column:
SELECT Customers.CustomerID as customer_id, Orders.CustomerID as order_id
FROM customers
inner JOIN orders
on customers.customerid=orders.customerid;
This is a peculiarity of some query interfaces. Your first query (which I would write like this) is:
SELECT c.CustomerID, o.CustomerID
FROM customers c INNER JOIN
orders o
ON c.customerid = o.customerid;
This returns two columns, both named CustomerId. Some query interfaces insist that the resulting columns be unique in the result set. Hence, the results ignore "subsequent" columns with the same name.
You can get a flavor of this by using the query as a subquery:
SELECT x.*
FROM (SELECT c.CustomerID, o.CustomerID
FROM customers c INNER JOIN
orders o
ON c.customerid = o.customerid
) x;
This should return an error, because CustomerId is ill-defined.
Three points to remember:
Most databases and query interfaces allow result sets with multiple columns with the same name.
No database allows multiple columns with the same name in a subquery.
You know how to fix this by assigning a column alias, which is a best-practice anyway.