MYSQL: Averaging the sum of two columns - mysql

Using MYSQL I am trying to get the avg amount spent by all the customers after determining the sum of what each customer spent.
select customernumber, round(sum(price_per_each*quantity_ordered),2) as 'ordertotal'
from orderdetails
join orders using (ordernumber)
join customers using (customernumber)
group by customernumber;
This gives me the sum of what each customer has spent across multiple orders. The results of this query are about hundred records, ranging from 8k to 900k.
I now need to get the avg of all the sum totals shown in the previous query. So far every time I try to write this, I get an error message regarding invalid use of group function.
When I try getting the average by using division via count(*), the number I get is in the 3k range which is too small compared to what is expected.
Please help. I am just starting to learn MySql and cannot seem to figure this out after several hours.

I would try the AVG function over the ordertotal column.
SELECT AVG(`ordertotal`)
FROM (
select customernumber, round(sum(price_per_each*quantity_ordered),2) as 'ordertotal'
from orderdetails
join orders using (ordernumber)
join customers using (customernumber)
group by customernumber
) nested;

Related

Using SQL to calculate average number of customers

Please see above for the data structure. I am trying to write an SQL query to get the average number of customers for each session
My attempt:
select avg(A.NumberCustomer)
from(
select SessionName, count(distinct customers.Idcustomer) as NumberCustomer,
from customers, enrollments, sessions
where customers.Idcustomer=enrollments.Idcustomer and enrollments.Idsession=sessions.Idsession
group by sessions.SessionName
) A
But I seem to get an error on the from customers, enrollments, sessions line
Not sure about this, any help appreciated.
Thanks
You have and extra comma that you should to delete:
select avg(A.NumberCustomer)
from(
select SessionName,
count(distinct customers.Idcustomer) as NumberCustomer, #<--- here
from customers, enrollments, sessions
where customers.Idcustomer=enrollments.Idcustomer
and enrollments.Idsession=sessions.Idsession
group by sessions.SessionName
) A
By the way, I suggest to you to move to SQL'99 join syntax for readability reasons:
SELECT
avg(A.NumberCustomer)
FROM (
select
SessionName,
count(distinct customers.Idcustomer) as NumberCustomer
from customers
inner join enrollments
on customers.Idcustomer=enrollments.Idcustomer
inner join sessions
on enrollments.Idsession=sessions.Idsession
group by sessions.SessionName
) A
Also, nice diagram on question and remember to include your error message next time.
For the average number of customers in each session, you should be able to use just the enrollments table. The average would be the number of enrollments divided by the number of sessions:
select count(*) / count(distinct idSession)
from enrollments e;
This makes the following assumptions:
All sessions have at least one customer (your original query had this assumption as well).
No customer signs up multiple times for the same session.

Joining two tables, including count, and sorting by count in MySQL

Have the need to run a bit more complex of a MySQL query. I have two tables that I need to join where one contains the primary key on the other. That's easy enough, but then I need to find the number of occurrences of each ID returned as well, and ultimately sort all the results by this number.
Normally this would just be a group by, but I also need to see ALL of the results (so if it were a group by containing 10 records, I'd need to see all 10, as well as that count returned as well).
So for instance, two tables could be:
Customers table:
CustomerID name address phone etc..
Orders table:
OrderID CustomerID product info etc..
The idea is to output, and sort the orders table to find the customer with the most orders in a given time period. The resultant report would have a few hundred customers, along with their order info below.
I couldn't figure out a way to have it return the rows containing ALL the info from both tables, plus the number of occurences of each in one row. (customer info, individual orders info, and count).
I considered separating it into multiple queries (get the list of top customers), then a bunch of sub-queries for each order programmatically. But that was going to end up with many hundreds of sub-queries every time this is submitted.
So I was hoping someone might know of an easier way to do this. My thought was to have a return result with repeated information, but get it only in one query.
Thanks in advance!
SELECT CUST.CustomerID, CUST.Name, ORDR.OrderID, ORDR.OrderDate, ORDR.ProductInfo, COUNTS.cnt
FROM Customers CUST
INNER JOIN Orders ORDR
ON ORDR.CustomerID = CUST.CustomerID
INNER JOIN
(
SELECT C.CustomerID, COUNT(DISTINCT O.OrderID) AS cnt
FROM Customers C
INNER JOIN Orders O
ON O.CustomerID = C.CustomerID
GROUP BY C.CustomerID
) COUNTS
ON COUNTS.CustomerID = CUST.CustomerID
ORDER BY COUNTS.cnt DESC, CustomerID
This will return one row per order, displayed by customer, ordered by the number of orders for that customer.

Compare individual to group

I am relatively new to MySQL. I have a huge database of salespeople and each sale they make, and for how much. I know that I can put AVG(SaleAmount) in a SELECT statement to get the average number of sales of the people at large, but I was wondering how I can get a list of each individuals' average sales, and then compare it to the group average to get a group of salesmen who are above that average.
I eventually want a list of those salespeople whose averages are two standard deviations above the group average.
I'm sorry if this is relatively simple, but I would really appreciate the help.
Join with a subquery that gets the global statistics.
SELECT s.id, s.name, AVG(SaleAmount) AS personAvg, avgSale, stdSale
FROM salespeople AS s
JOIN (SELECT AVG(SaleAmount) AS avgSale, STDDEV(SaleAmount) AS stdSale
FROM salespeople) AS av
GROUP BY s.id
HAVING personAvg > avgSale + 2 * stdSale

Mysql: Searching for data by month only yields one result not all of them

I have an Orders table with the Date_ordered column.
I am trying to select the average price of all of the items ordered that were purchased in the month of December.
I used
select *, avg(price) from orders where monthname(date_ordered) = "december"
However it is only coming up with one result, when my table has 4 instances of the date being xxxx-12-xx
Note: There are multiple years included in the data but they are irrelevant to the query I need
avg() in your query is a group function. If there is no GROUP BY clause in your query, it causes the group function to be applied on all selected rows. So you are getting average of the four prices in that field. And the average is only one.
When you put avg() into the select, you turn the query into an aggregation query. Without a group by, SQL always returns on row. If you want the average as well as the other data, then use a join or subselect:
select o.*, oo.avgp
from orders o cross join
(select avg(price) as avgp from orders where month(date_ordered) = 12) oo
where month(o.date_ordered) = 12;
AVG() is an aggregate function. It averages every value in the price column and condenses the result into a single row. You could group your result by another column, or consider if you really want to use avg()

MYSQL Count group by rows ignoring effect of JOIN and SUM fields on Joined tables

I have 3 tables:
Orders
- id
- customer_id
Details
- id
- order_id
- product_id
- ordered_qty
Parcels
- id
- detail_id
- batch_code
- picked_qty
Orders have multiple Details rows, a detail row per product.
A detail row has multiple parcels, as 10'000 ordered qty may come from 6 different batches, so goods from batches are packed and shipped separately. The picked quantity put in each parcel for a detail row should then be the same as the ordered_qty.
... hope that makes sense.
Im struggling to write a query to provide summary information of all of this.
I need to Group By customer_id to provide a row of data per customer.
That row should contain
Their total number of orders
Their total ordered_qty of goods across all orders
Their total picked_qty of goods across all orders
I can get the first one with:
SELECT customer_id, COUNT(*) as number_of_orders
FROM Orders
GROUP BY Orders.customer_id
But when I LEFT JOIN the other two tables and add the
SELECT ..... SUM(Details.ordered_qty) AS total_qty_ordered,
SUM(Parcels.picked_qty) AS total_qty_picked
.. then I get results that dont seem to add up for the quantities, and the COUNT(*) seems to include the additional lines from the JOIN which obviously then isn't giving me the number of Orders anymore.
Not sure what to try next.
===== EDIT =======
Here's the query I tried:
SELECT
customer_id,
COUNT(*) as number_of_orders,
SUM(Details.ordered_qty) AS total_qty_ordered,
SUM(Parcels.picked_qty) AS total_qty_picked
FROM Orders
LEFT JOIN Details ON Details.order_id=Order.id
LEFT JOIN Parcels ON Parcels.detail_id=Detail.id
GROUP BY Orders.customer_id
try COUNT(distinct Orders.order_id) as number_of_orders,
as in
SELECT
customer_id,
COUNT(distinct Orders.order_id) as number_of_orders,
SUM(Details.ordered_qty) AS total_qty_ordered,
(select SUM(Parcels.picked_qty)
FROM Parcels WHERE Parcels.detail_id=Detail.id ) AS total_qty_picked
FROM Orders
LEFT JOIN Details ON Details.order_id=Order.id
GROUP BY Orders.customer_id
EDIT: added an other select with subselect
Is there any particular reason you feel the need to combine all these in one query? Simplify by breaking it up in to separate queries, and if you want a single call to get the results, put the queries in a stored procedure, using temp tables.