mysql sum total number of rows by customerid show desc order - mysql

I have a question my professor gave me, on making a statement that goes like this
How many customers are “whales” i.e., have spent, in their lifetime, more than $4,000? How many are “shrimps,” having spent less than $20?
This is the online database we are using: http://www.w3schools.com/sql/trysql.asp?filename=trysql_select_all
run this query to create another table before helping me out if you can
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;
I am trying to combine every customers order together grouping the sum by the customerID and then showing it in the table as a row for each customer ID and total amount they have order from subtotal
SELECT customerID, SUM(subtotal) AS 'total_money_spent' FROM ByCustomerOrders GROUP BY customerID ORDER BY 'total_money_spent' DESC LIMIT 1;
That didn't seem to work as it shows a value of 111. anyone see an issue?

You have a LIMIT 1 at the end of your statement which will only show the first result.
When you run:
SELECT customerID, SUM(subtotal) AS 'total_money_spent' FROM ByCustomerOrders GROUP BY customerID ORDER BY 'total_money_spent' DESC;
It outputs all the totals grouped

Related

Error 1064 - In statement

I am trying to show the average price of products bought by customers from ‘Tucson’, however this query returns null even though there are two customers that have placed orders from Tuscon.
select AVG(product_price) from product where product_id in
(select product_id from orderline where order_id in
(select order_id from ordertable where cust_id in
(Select cust_id from customer where city = 'Tuscon')))
You're using fom instead of from in your query: select order_id fom ordertable where cust_id in
This should be select order_id from ordertable where cust_id in
fom is not a recognized keyword. The MySQL parser doesn't know what to do with that, so it throws an error about "invalid syntax".
Consider using join operations in place of nested IN subqueries. If we are guaranteed:
product_id is unique in product table
order_id is unique in ordertable table
cust_id is unique in customer table
then we can get an equivalent result set, the average of the price of distinct products that were ordered...
SELECT AVG(p.product_price)
FROM ( SELECT l.product_id
FROM orderline l
JOIN ordertable o
ON o.order_id = l.order_id
JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'
GROUP BY l.product_id
) q
JOIN product p
ON p.product_id = l.product_id
If we want that "average price" of all products ordered (a different result, with the average taking into account the number of times a product was ordered...then we could use a query like this:
SELECT AVG(p.product_price)
FROM product p
JOIN orderline l
ON l.product_id = p.product_id
JOIN ordertable o
ON o.order_id = l.order_id
JOIN customer c
ON c.cust_id = o.cust_id
WHERE c.city = 'Tuscon'

MYSQL view groupby

Below is the cutomerOrdersByName View:
# Returns total for each order ordered from largest to smallest.
DROP VIEW IF EXISTS customerOrdersByName;
CREATE VIEW customerOrdersByName AS
SELECT d.orderNumber
, customerName
, round(SUM(quantityOrdered * priceEach),2) total
FROM orderDetails d
INNER JOIN orders o ON o.orderNumber = d.orderNumber
INNER JOIN customers c ON c.customerNumber = o.customerNumber
GROUP BY customerName
ORDER BY total DESC;
How do I modify the customerOrdersByName view so that it groups and orders the totals by customer name and then by total from highest to lowest?
By modifying order by clause:
GROUP BY customerName
ORDER BY customerName asc, total DESC;
However, I do not get the order number in the select list. If you do not group by on it, you should also remove it from the select list.

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.

Rows with Revenue =0, how do I show the 0?

The following code shows all our customers that have made purchases since our database was created and how much money they have spent. There are a couple customers that have not made purchases since we implemented the new database but they are not appearing when I run this code. I have looked around this site for similar examples but the solutions are too complex for me.
There is also a customers table that shows the results for all of our 'n' customers, that table connects to the orders table through customerID. Not sure if that will help.
select t3.CustomerID, sum(Revenue) as Revenue
from
(
select orderid, sum(UnitPrice*quantity) as Revenue from [Order Details]
group by OrderID
)t1
inner join
(
select customerid,orderid from orders
)t3
on t1.orderid=t3.orderid
group by t3.CustomerID
I think you just want this rather simpler query:
select c.CustomerID, sum(od.UnitPrice * od.quantity) as Revenue
from customers c left outer join
orders o
on o.CustomerId = c.CustomerId left outer join
`Order Details` od
on od.OrderId = o.OrderId
group by c.CustomerID;

Can I execute a COUNT() before GROUP BY

I am working on an mySQL assignment for school and I am stuck on a question. I am still new to mySQL. COUNT(o.customer_id) is not working the way I want. I want it to count the number of orders but it is counting all items. i.e. Customer 1 has 2 orders but it is returning 3 because one order has two items. I have three tables one with customers, another with orders than another with each item on each order. Ive posed my query below. Any help would be great.
SELECT email_address, COUNT(o.order_id) AS num_of_orders,
SUM(((item_price - discount_amount) * quantity)) AS total
FROM customers c JOIN orders o
ON c.customer_id = o.customer_id
JOIN order_items ot
ON o.order_id = ot.order_id
GROUP BY o.customer_id
HAVING num_of_orders > 1
ORDER BY total DESC;
As simple as use Distinct reserved word:
SELECT email_address, COUNT(distinct o.order_id) AS num_of_orders
Looks like you want to count the DISTINCT number of orders. Add a DISTINCT into the COUNT. Although MySQL allows you to use the SELECT expression in the HAVING clause, it's not good practice to do so.
SELECT email_address, COUNT(DISTINCT o.order_id) AS num_of_orders,
SUM(((item_price - discount_amount) * quantity)) AS total
FROM customers c JOIN orders o
ON c.customer_id = o.customer_id
JOIN order_items ot
ON o.order_id = ot.order_id
GROUP BY o.customer_id
HAVING COUNT(DISTINCT o.order_id) > 1
ORDER BY total DESC;
Just take out the join to items. All it is doing is duplicating rows when there are multiple items.
SELECT email_address, COUNT(o.order_id) AS num_of_orders,
SUM(((item_price - discount_amount) * quantity)) AS total
FROM customers c JOIN orders o
ON c.customer_id = o.customer_id
GROUP BY o.customer_id
HAVING COUNT(o.order_id) > 1
ORDER BY total DESC;