Group by isnt calculating quantity and price? - mysql

I am trying to export sales report from table 'sales'
It has field names pname, price, sold_to, pquantity, pamount, date
Here I don't wish to display the same company I sold_to over and over if the company purchased same product on 2021-02-13 so I tried to group by the query but then it isn't showing total sum of pquantity and pamount in results even though it groups same company.
could someone help me out with fixing the query?
Here is my MYSQL query:
SELECT * FROM sales
WHERE DATE_FORMAT(date, '%Y-%m-%d') BETWEEN '$from' AND '$to'
GROUP BY pname, sold_to, pquantity, pamount, date
ORDER BY sale_id DESC
I am definitely doing it wrong would appreciate if someone could help me correct the logic.

You need to use SUM() to get sum of quantity and amount
SELECT pname, sold_to, date, SUM(pquantity), SUM(pamount)
FROM sales
WHERE DATE_FORMAT(date, '%Y-%m-%d') BETWEEN '$from' AND '$to'
GROUP BY pname, sold_to, date
ORDER BY sale_id DESC

Related

Group by not working as expected

Needs help with my SQL query
Query :
Select customer_id,
if (call_details ='International' , 'International Calls', 'National Calls'),
sum(minutes)
from call_minutes
where date between '$from' and '$to'
group by call_details
My Result is displaying as below
Please let me know why National Calls is not getting grouped. I wanted to find the sum of national calls and international calls
use below SQL:
select customer_id,
call_details,
sum(minutes) as minutes
from(
Select customer_id,
if (call_details ='International' , 'International Calls', 'National Calls') as call_details,
minutes
from call_minutes
where date between '$from' and '$to') x
group by customer_id,call_details
You don't need a subquery for this, because MySQL allows you to use column aliases in the group by (not all databases do). So:
Select customer_id,
(case when call_details = 'International'
then 'International Calls'
else 'National Calls'
end) as call_group,
sum(minutes)
from call_minutes
where date between '$from' and '$to'
group by customer_id, call_group;
Note: this assumes that you want separate rows for each customer. If not, remove customer_id from both the select and the group by:
Select (case when call_details = 'International'
then 'International Calls'
else 'National Calls'
end) as call_group,
sum(minutes)
from call_minutes
where date between '$from' and '$to'
group by call_group;
If you want a list of customer ids in each group, you can always add group_concat(customer_id).

Merging multiple MySQL SELECT statements calculating fields

I've had a look at this question (Please help merging 4 MySQL queries to One) hoping it would help, but it doesn't. I can't make sense of it because my brain is fried.
I'm trying to get my head around merging four SELECT statements, all of which work individually, into one.
The fields are;
QUANTITY: INT;
ORDERDATE: DATE; // Not datetime - I don't need time.
MySQL Version 5.6.17
The data I'm retrieving is;
1) Number of products ordered this financial year;
SELECT SUM(QUANTITY) AS YTD
FROM ORDERDETAILS
WHERE ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16"
Note that in Australia the Financial Year is 1st of July through to 30th of June.
2) Number of products ordered this month;
SELECT SUM(QUANTITY) AS MONTHY
FROM ORDERDETAILS
WHERE ORDERDATE BETWEEN "2017-02-01" AND "2017-02-16"
3) Number of products ordered today;
SELECT SUM(QUANTITY) AS TODAYS
FROM ORDERDETAILS
WHERE ORDERDATE = "2017-02-16"
4) Average number of products ordered per order;
SELECT AVG(QUANTITY) AS BOOGER
FROM ORDERDETAILS
WHERE ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16"
I want to avoid sending four separate statements to the server. Perhaps it can't be done, but if I could achieve the same results in a single statement I'd be happy.
I've looked at joins, embedding select within selects but can't get my head around it.
Once I get the data all I do is update a couple of labels on a form (Delphi).
Any tips that a nearly 55 year old brain can handle would be appreciated.
You can do this using case when condition:
select
sum(case when ORDERDATE BETWEEN '2016-07-01' AND '2017-02-16' then QUANTITY end ) as YTD,
sum(case when ORDERDATE BETWEEN '2017-02-01' AND '2017-02-16' then QUANTITY end ) as MONTHY,
sum(case when ORDERDATE = '2017-02-16' then QUANTITY end ) as TODAYS,
AVG(case when ORDERDATE BETWEEN '2016-07-01' AND '2017-02-16' then QUANTITY end ) as BOOGER
FROM ORDERDETAILS
You simply have to use a different alias on the different calls to the table and put it all in one SELECT statement as follows:
SELECT SUM(od1.QUANTITY) AS YTD,
SUM(od2.QUANTITY) AS MONTHLY,
SUM(od3.QUANTITY) AS TODAYS,
AVG(od4.QUANTITY) AS BOOGER
FROM ORDERDETAILS od1,
ORDERDETAILS od2,
ORDERDETAILS od3,
ORDERDETAILS od4
WHERE od1.ORDERDATE BETWEEN CAST('2016-07-01' AS DATE) AND CAST('2017-02-16' AS DATE)
AND od2.ORDERDATE BETWEEN CAST('2017-02-01' AS DATE) AND CAST('2017-02-16' AS DATE)
AND od3.ORDERDATE = CAST('2017-02-16' AS DATE)
AND od4.ORDERDATE BETWEEN CAST('2016-07-01' AS DATE) AND CAST('2017-02-16' AS DATE)
Use SUM(IF()) pattern and move condition inside the IF.
SELECT
SUM(IF(ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16", QUANTITY, 0)) AS YTD,
SUM(IF(ORDERDATE BETWEEN "2017-02-01" AND "2017-02-16", QUANTITY, 0)) AS MONTHY,
SUM(IF(ORDERDATE = "2017-02-16", QUANTITY, 0)) AS TODAYS,
SUM(IF(ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16", QUANTITY, 0)) / COUNT(IF(ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16", 1, NULL)) AS BOOGER
FROM ORDERDETAILS
WHERE ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16";
Consider using CURDATE() for today's date.
Also a WHERE clause can be added so that all rows of table are not scanned e.g. WHERE ORDERDATE BETWEEN "2016-07-01" AND "2017-02-16" after FROM ORDERDETAILS

Finding Average based on more than one variable

I have to find the average amount spent by accounts which have been used at least once in 2012 for each payment type in each month of 2012. The tables I am using have Transactions: account_id, purchase_date, payment_type and amount
Games: account_id, game_id and game_date
So far I have
SELECT SUM(amount) FROM Transactions
WHERE DATE (purchase_date) BETWEEN '2012-01-01' AND '2012-12-31'
AND account_id in (SELECT account_id FROM Games WHERE (Games.game_date)
BETWEEN '2012-01-01' AND '2012-12-31') GROUP BY payment_type;
I am at a loss as to how to move this further along. The results I have so far only show one column so I don't even know which amount is for which payment type. How can I show the payment types beside these and then average them based on the number of transactions made per month?
EDIT
So I have
SELECT payment_type, AVG(amount) FROM Transactions
WHERE DATE (purchase_date) BETWEEN '2012-01-01' AND '2012-12-31'
AND account_id in (SELECT account_id FROM Games WHERE (Games.game_date)
BETWEEN '2012-01-01' AND '2012-12-31') GROUP BY payment_type;
which shows me the average spent per payment method across 2012, I only need to sort this by the month now.
Once you have the sum for payment_type (using you query as table)
select avg(tot) from (
SELECT payment_type, SUM(amount) as tot FROM Transactions
WHERE DATE (purchase_date) BETWEEN '2012-01-01' AND '2012-12-31'
AND account_id in (SELECT account_id FROM Games WHERE (Games.game_date)
BETWEEN '2012-01-01' AND '2012-12-31') GROUP BY payment_type
) t
OR could be you need only
SELECT payment_type, SUM(amount), AVG(amount)
FROM Transactions
WHERE DATE (purchase_date) BETWEEN '2012-01-01' AND '2012-12-31'
AND account_id in (SELECT account_id FROM Games WHERE (Games.game_date)
BETWEEN '2012-01-01' AND '2012-12-31')
GROUP BY payment_type

Name of customer with highest sale monthwise

I have a sales table from which I select the total sales per month , highest sale , number of sale for all the months in the current year, using
select monthname(date),sum(amt_c),MAX(amt_c)
from sales where year(date)= year(now())
group by monthname(date) ;
I want to also select the customer who has done the highest purchase , i.e the customer correponding to the MAX(amt_c).
amt_c is the purchase done by the customer,
One way is a filtering join:
select filter.mn
, filter.sum_sales
, filter.max_sales
, sales.cust
from (
select monthname(date) as mn
, sum(amt_c) as sum_sales
, max(amt_c) as max_sales
from sales
where year(date) = year(now())
group by
mn
) filter
join sales
on monthname(sales.date) = filter.mn
and sales.amt_c = filter.max_sales
For more approaches, browse the greatest-n-per-group tag.
select v.monthname,
v.sum_amt_c,
v.max_amt_c,
count(s.amt_c) as num_of_amounts,
group_concat(s.cust) as customers
from (select monthname(date) as monthname,
sum(amt_c) as sum_amt_c,
max(amt_c) as max_amt_c
from sales
where date between concat(year(now()), '-01-01') and concat(year(now()), '-12-31')
group by monthname(date)) v
join sales s
on v.max_amt_c = s.amt_c
and v.monthname = monthname(s.date)
and s.date between concat(year(now()), '-01-01') and concat(year(now()), '-12-31')
group by v.monthname, v.sum_amt_c, v.max_amt_c
order by month(s.date)
This is similar to Andomar's answer however it provides the following benefits:
If your DATE field is indexed (it should be) the above query will use that index. You should not have criteria on a date field with a function applied to it. MySQL does not support function based indexes, so it is a given that year(date) is not indexed. date may be indexed, however.
This sorts the results by month # (1-12) but shows the month name.
In the event that the same 2+ customers are tied, this will list all of them, and show only one row for that month. You would otherwise potentially have 2, 3, 4+ rows for a single month in the event of a tie. This is done via MySQL's GROUP_CONCAT function.

Select average monthly count, grouped by a field

I'm not sure if this has been asked before, as I don't know how to best phrase this question.
Given a query like:
SELECT DATE_FORMAT(i.created, '%Y-%m') as 'period',
COUNT(id) as 'total',
i.company_id
FROM invoice i
GROUP BY period, i.company_id
ORDER BY period DESC, total DESC
How can I return the average and/or mean count per month, grouped by company_id? It is important to only count those periods where there actually are any invoices.
If you want to exclude zero months then add HAVING condition and then select AVG() for each company using your query as a base:
SELECT company_id, AVG(total)
FROM
(SELECT DATE_FORMAT(i.created, '%Y-%m') as 'period',
COUNT(id) as 'total',
i.company_id
FROM invoice i
GROUP BY period, i.company_id
HAVING COUNT(id)>0
) as T1
GROUP BY company_id