Write an SQL Query to calculate total purchase amount of each customer - mysql

I'm trying to calculate the total purchase amount of each customer from the database available online on W3 Schools
The tables I'm using are:
Customers
Orders
Products
OrderDetails
My current query gives me the product wise purchase amount for the customer. What I need is the total purchase amount.
SELECT c.CustomerID,o.OrderID,(ord.Quantity*p.Price) as
Total_Amount
from Customers c inner join Orders o
inner join Products p
inner join OrderDetails ord
on c.CustomerID = o.CustomerID
and o.OrderID = ord.OrderID
and ord.ProductID = p.ProductID;
My Output:
I need the sum for the values with the same order id and customer id.
I tried out group-by and sum but it gives me the overall sum of all the products.

You simply want a GROUP BY:
SELECT c.CustomerID, SUM(ord.Quantity*p.Price) as
Total_Amount
FROM Customers c inner join Orders o
on c.CustomerID = o.CustomerID join
OrderDetails ord
on o.OrderID = ord.OrderID join
Products p
on ord.ProductID = p.ProductID
GROUP BY CustomerID;
Note that this orders the JOINs so the ON clauses are interleaved. This is how JOINs are normally written.

If you need the sum for the values with the same order id and customer id, then you need to group the rows based on both customer id and order id.
SELECT c.CustomerID,o.OrderID,SUM(ord.Quantity*p.Price) as Total_Amount
from Customers c inner join Orders o
inner join Products p
inner join OrderDetails ord
on c.CustomerID = o.CustomerID
and o.OrderID = ord.OrderID
and ord.ProductID = p.ProductID
Group By c.CustomerID,o.OrderID

Related

Joining multiple tables to show last order date by customer, by product and by vendor

I am trying to solve the following query, there's a few additional parameters, but these are the main attributes required:
Provide the product details, which vendors supply these products, and what was the last date these products were ordered by customers.
I have my original query below which gets me 90% of the way. I just can't seem to figure out how to display the last order date by customer per individual product. I've tried embedding (select max(o.OrderDate) from orders as o) into my select statement, but it only displays the latest order date of all of the products, not the individual per product last order date (e.g., all dates listed are 01/01/2020 when I know other products' last order date was before this date).
Apologies, I do not have enough rep to post pictures in line with text, therefore I have attached pictures of table structure and my query.
SQL Query
Table structure
Query:
select distinct p.ProductNumber, p.ProductName, p.RetailPrice, p.QuantityOnHand, v.VendName,
(select max(o.OrderDate)
from orders as o)
as LastOrderDateByCust
from ((((orders as o
inner join order_details as od
on od.OrderNumber = o.OrderNumber)
inner join products as p
on p.ProductNumber = od.ProductNumber)
inner join product_vendors as pv
on p.ProductNumber = pv.ProductNumber)
inner join vendors as v
on pv.VendorID = v.VendorID)
where p.QuantityOnHand < '10'
order by LastOrderDateByCust DESC;`
figured it out on my own I believe:
select distinct p.ProductNumber, p.ProductName, c.CategoryDescription, p.RetailPrice, pv.WholesalePrice, p.QuantityOnHand, v.VendName, pv.DaysToDeliver, (select max(o.OrderDate)
from orders as o
inner join order_details as od
on o.OrderNumber = od.OrderNumber
where od.ProductNumber = p.ProductNumber)
as LastOrderDateByCust
from (((((orders as o
inner join order_details as od
on o.OrderNumber = od.OrderNumber)
inner join products as p
on p.ProductNumber = od.ProductNumber)
inner join product_vendors as pv
on p.ProductNumber = pv.ProductNumber)
inner join vendors as v
on pv.VendorID = v.VendorID)
inner join categories as c
on p.CategoryID = c.CategoryID)
where od.ProductNumber = p.ProductNumber and p.QuantityOnHand < '10'
order by p.ProductNumber;`

Combining two queries and getting the sum of count

I have two different queries that each do half the job I need. how to combine them.
orders table has orderNumber and customerNumber, customers table has customerNumber and salesRepEmployeeNumber, orderdetails has multiple lines of the same orderNumber each showing price&quantity of different items).
(counting the number of orders from different customers each sales rep has)
select c.salesRepEmployeeNumber, count(*)
from customers c
inner join orders o1
on c.customerNumber = o1.customerNumber
group by c.salesRepEmployeeNumber;
and
(counting the revenue made by each sales rep)
select c.salesRepEmployeeNumber, sum(o2.priceEach*o2.quantityOrdered) as "Revenue"
from customers c
inner join orders o1
on c.customerNumber = o1.customerNumber
inner join orderdetails o2
on o1.orderNumber = o2.orderNumber
group by c.salesRepEmployeeNumber;
I need a query to know the employee number, # of orders, and revenue. I tried
select sum(o2.priceEach*o2.quantityOrdered) as "Revenue", c.salesRepEmployeeNumber, count(*)
from customers c
inner join orders o1
on c.customerNumber = o1.customerNumber
inner join orderdetails o2
on o1.orderNumber = o2.orderNumber
group by c.salesRepEmployeeNumber;
but it returns the count of items/products from the orders (e.g. 1 order has three products)
SELECT salesRepEmployeeNumber,
t1.`count(*)` AS `count`,
t2.Revenue
FROM (complete text of 1st query) AS t1
LEFT JOIN (complete text of 2nd query) AS t2 USING (salesRepEmployeeNumber)
complete text means "without final semicolon".
If your data guarantees that the amount of rows produced by 2nd query is equal to one produced by 1st query then you may use not LEFT but INNER joining.
Also test
select c.salesRepEmployeeNumber
, COUNT(DISTINCT o1.id) AS orders_count
, sum(o2.priceEach*o2.quantityOrdered) as "Revenue"
from customers c
join orders o1
on c.customerNumber = o1.customerNumber
join orderdetails o2
on o1.orderNumber = o2.orderNumber
group
by c.salesRepEmployeeNumber;
where o1.id is primary key expression (or any unique non-NULL column/expression/index) of orders table.

SQL Get all orders which contain exclusively one kind of item

In this Database I want to count the number of orders that contain only products of a certain category.
I know how to count all orders that also contain items of a certain category, i.e. category 1:
SELECT Count(DISTINCT orderdetails.orderid) AS "AllCat1"
FROM orderdetails
INNER JOIN orders
ON orderdetails.orderid = orders.orderid
AND orderdetails.productid IN (SELECT DISTINCT productid
FROM products
WHERE categoryid = 1)
WHERE orderdate BETWEEN "1996-12-01" AND "1996-12-31";
I am having trouble finding an elegant way to get all orders that contain only category 1 items. I tried selecting all OrderIDs and grouping them by OrderID AND CategoryID:
SELECT *
FROM orderdetails
INNER JOIN orders
ON orderdetails.orderid = orders.orderid
AND orderdate BETWEEN "1996-12-01" AND "1996-12-31"
INNER JOIN products
ON orderdetails.productid = products.productid
GROUP BY orderdetails.orderid,
categoryid;
But I have no idea how to count all OrderIDs that contain category 1 items exclusively. Is my approach right? Or is there a better way to do it (Which I am sure there is)
You can use group by and having . . . but you need two levels. To get the orders that are all in one (or a set of categories) by doing:
SELECT o.orderId
FROM orders o JOIN
orderdetails od
ON od.orderid = o.orderid JOIN
products p
ON p.productid = od.productid
WHERE o.orderdate BETWEEN '1996-12-01' AND '1996-12-31'
GROUP BY o.orderId
HAVING SUM(CASE WHEN p.categoryid IN (1) THEN 1 ELSE 0 END) = COUNT(*);
The count needs a subquery:
SELECT COUNT(*)
FROM (SELECT o.orderId
FROM orders o JOIN
orderdetails od
ON od.orderid = o.orderid JOIN
products p
ON p.productid = od.productid
WHERE o.orderdate BETWEEN '1996-12-01' AND '1996-12-31'
GROUP BY o.orderId
HAVING SUM(CASE WHEN p.categoryid IN (1) THEN 1 ELSE 0 END) = COUNT(*)
) o;
You can do filtering using HAVING clause. We basically Count the order details rows where category is 1 for an order. It should be equal to the total count of rows for that order. This would ensure that all the categories in an order is 1 only.
SELECT od.orderid
FROM orderdetails AS od
INNER JOIN orders AS o
ON od.orderid = o.orderid
AND o.orderdate BETWEEN "1996-12-01" AND "1996-12-31"
INNER JOIN products AS p
ON od.productid = p.productid
GROUP BY od.orderid
HAVING COUNT(CASE WHEN p.categoryid = 1 THEN 1 END) = COUNT(*)
It is advisable to use Aliasing in case of multi-table queries for Code clarity and readability

inner-join mysql x3

I need to display cust_id, the customer forename and surname, the product name<-(from products table) and date of sale<--(from sales table), also I need to display in order of the most recent dates first.
This is what I have got so far:
SELECT
customer.cust_id,
customer.forename,
customer.surname,
products.prod_name,
sales.Date_of_sale
FROM customers c
INNER JOIN sales s ON c.cust_id = s.cust_id
INNER JOIN products p ON s.product_id = p.product_id
ORDER BY s.Date_of_sale DESC
Any help would be appreciated.
This
SELECT
c.cust_id,
c.forename,
c.surname,
p.prod_name,
s.Date_of_sale
FROM customers c
INNER JOIN sales s ON c.cust_id = s.cust_id
INNER JOIN products p ON s.product_id = p.product_id
ORDER BY s.Date_of_sale DESC
will work

MySQL get top 3 suppliers from table

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.