Mysql Query: How many sum() recommended in single query? - mysql

I have 70 different types of accounts. And I am fetching the data as per the account type.
The query like this,
$mainData = "SELECT
count(*) AS totalRows,
sum(pay) as totalPay
sum(case when account_type = 1 then 1 else 0 end) AS account_1_Total,
sum(case when account_type = 1 then pay else 0 end) AS account_1_Pay,
sum(case when account_type = 2 then 1 else 0 end) AS account_2_Total,
sum(case when account_type = 2 then pay else 0 end) AS account_2_Pay,
{all_account_types_here}
FROM account_table";
In the end, those sum() are about more than 140.
So the question is, how many sum() is recommended in a single query?
Thanks!
EDITED:
The GROUP BY is the solution of it.

Related

Can I get average of a column in mySQL DB based upon value of other column in one query?

I have a table of phone call activity for a client. In the table, I have one column for the length of the call (in seconds), and another column for "first time call" (true / false). I was hoping to find a way to get the average call length of first time calls separated from the average time of non first time calls? Is this doable in a singe mySQL query?
SELECT location,
count(*) AS total,
sum(case when firstCall = 'true' then 1 else 0 end) AS firstCall,
sum(case when answered = 'Yes' then 1 else 0 end) AS answered,
sum(case when tags like '%Lead%' then 1 else 0 end) as lead,
sum(case when tags like '%arbage%' then 1 else 0 end) as garbage,
avg(case when duration........firstTime = True???)
FROM staging
GROUP BY location
SELECT location,
count(*) AS total,
sum(case when firstCall = 'true' then 1 else 0 end) AS firstCall,
sum(case when answered = 'Yes' then 1 else 0 end) AS answered,
sum(case when tags like '%Lead%' then 1 else 0 end) as lead,
sum(case when tags like '%arbage%' then 1 else 0 end) as garbage,
sum(case when firstCall='true' then duration else 0 end)/sum(case when firstCall = 'true' then 1 else 0 end) as first_call_true_average,
sum(case when firstCall='false' then duration else 0 end)/sum(case when firstCall = 'false' then 1 else 0 end) as first_call_false_average
FROM staging
GROUP BY location
I would phrase this as:
select
location,
count(*) as total,
sum(firstcall = 'true' ) as cnt_firstcall,
sum(answered = 'Yes' ) as cnt_answered,
sum(tags like '%Lead%' ) as cnt_lead,
sum(tags like '%arbage%') as cnt_garbage,
avg(case when firstcall = 'true' then duration end) as avg_first_call,_duration
avg(case when firstcall = 'false' then duration end) as avg_non_first_call_duration
from staging
group by location
Rationale:
MySQL interpret true/false conditions as 1/0 values in numeric context, which greatly shortens the conditional sum()s
avg() ignores null values, so a simple case expression is sufficient to compute the conditional averages

How to sum a field for two times with two conditions in the same SQL Statements

I have the following SQL statements:
Select SUM (amount) from accounts Where acctype = 0;
and
Select SUM (amount) from accounts Where acctype = 1;
I want to find the difference between the amount in two cases in a single SQL statement.
This is called conditional aggregation:
SELECT
SUM(case when acctype = 0 then amount else 0 end) AS sum0,
SUM(case when acctype = 1 then amount else 0 end) AS sum1,
SUM(case when acctype = 0 then amount else 0 end) -
SUM(case when acctype = 1 then amount else 0 end) AS diff
FROM accounts;
You can use conditional aggregation:
select sum(case when acctype = 0 then amount
when acctype = 1 then - amount
end) as diff
from accounts;

SQL count with having clause wrong result

I'm trying to understand how to count mysql row's according to HAVING.
SELECT COUNT(*),
SUM(CASE WHEN sentby='$user_id' AND hiddenbysentby=0 THEN 1 ELSE 0 END) as sentbyuser,
SUM(CASE WHEN sentto='$user_id' AND hiddenbysentto=0 THEN 1 ELSE 0 END) as senttouser
FROM cb_users.user_pm
WHERE title LIKE '%$search%'
HAVING senttouser = 1 OR sentbyuser = 1
I want to count rows that are matching these criteria
SUM(CASE WHEN sentby='$user_id' AND hiddenbysentby=0 THEN 1 ELSE 0 END)
SUM(CASE WHEN sentto='$user_id' AND hiddenbysentto=0 THEN 1 ELSE 0 END)
I have second function that display this data without COUNT(*), and it works fine.
But this query selects all rows no matter if hiddenbysentby = 1 or 0 AND hiddenbysentto = 1 or 0
You should change your HAVING clause to:
HAVING senttouser >= 1 OR sentbyuser >= 1
When you are summing rows, your values are going to equal the total number of rows located for each, therefore, unless you only had exactly one row that meets your criteria, you won't get the result you're looking for.
You should move condition by hiddenbysentby and hiddenbysentto fields in WHERE clause and add a condition by user id
SELECT COUNT(*),
SUM(CASE WHEN sentby='$user_id' THEN 1 ELSE 0 END) as sentbyuser,
SUM(CASE WHEN sentto='$user_id' THEN 1 ELSE 0 END) as senttouser
FROM cb_users.user_pm
WHERE title LIKE '%$search%' AND (hiddenbysentby=0 AND sentby='$user_id') OR (hiddenbysentto=0 AND sentto='$user_id')
HAVING senttouser = 1 OR sentbyuser = 1

Pivoting Data Using MySql

Objective 1:
Your sales data is stored in the Purchases table.
Your sales staff wants to see the sales data in a pivoted form, broken down by quarter.
If your Purchases table doesn't have sales data, create some. Be sure the data spans four quarters.
Next, write a query to pivot the data as follows:
Album Q1 Q2 Q3 Q4
OK Computer 2 5 3 7
Sea Change 8 6 2 1
Do not create a separate table or a view. Do not alter any tables.
Save your query as dba1lesson10project1.sql and hand in the project.
This is What I need to do. But, the table it wants me to work with looks like this. And it states in the assignment I cannot alter it at all.
CustomerID DateOfPurchase SongID
1 2007-03-31 3
3 2007-06-30 4
4 2007-09-30 4
5 2007-12-31 5
I have tried
SELECT SongID,
SUM(CASE WHEN DateOfPurchase = '2007-03-31' THEN DateOfPurchase ElSE 0 END) AS 'Q1',
SUM(CASE WHEN DateOfPurchase = '2007-06-30' THEN DateOfPurchase ELSE 0 END) AS 'Q2',
SUM(CASE WHEN DateOfPurchase = '2007-09-30' THEN DateOfPurchase ELSE 0 END) AS 'Q3',
SUM(CASE WHEN DateOfPurchase = '2007-12-31' THEN DateOfPurchase ELSE 0 END) AS 'Q4'
FROM Purchases
GROUP BY SongID;
Along with other variants:
SELECT SongID,
SUM(CASE WHEN DateOfPurchase = '2007-03-31' THEN CustomerID ElSE 0 END) AS 'Q1',
SUM(CASE WHEN DateOfPurchase = '2007-06-30' THEN CustomerID ELSE 0 END) AS 'Q2',
SUM(CASE WHEN DateOfPurchase = '2007-09-30' THEN CustomerID ELSE 0 END) AS 'Q3',
SUM(CASE WHEN DateOfPurchase = '2007-12-31' THEN CustomerID ELSE 0 END) AS 'Q4'
FROM Purchases
GROUP BY SongID;
And:
SELECT SongID,
SUM(CASE WHEN DateOfPurchase = '2007-03-31' THEN SongID ElSE 0 END) AS 'Q1',
SUM(CASE WHEN DateOfPurchase = '2007-06-30' THEN SongID ELSE 0 END) AS 'Q2',
SUM(CASE WHEN DateOfPurchase = '2007-09-30' THEN SongID ELSE 0 END) AS 'Q3',
SUM(CASE WHEN DateOfPurchase = '2007-12-31' THEN SongID ELSE 0 END) AS 'Q4'
FROM Purchases
GROUP BY SongID;
Which, the last 2 almost get me what I need. But, there is only one purchase per SongID and Quarter. They show me either the CustomerID or SongID instead. I have a basic understand of what I need to do. But without being able to alter the table to show how many purchases there have actually been I'm not sure what to do. Any suggestions?
Your current query is very close, I would suggest a few minor changes. You are hard-coding the date but what happens if you have a date in quarter one that is not equal to 2007-03-31 it won't show up.
I would use the QUARTER() function in MySQL, this will return the quarter 1-4 based on the date value.
Second, I don't think you want to sum the SongID, in your CASE expression I would replace the SongID with 1 similar to the following:
SELECT SongID,
SUM(CASE WHEN Quarter(DateOfPurchase) = 1 THEN 1 ElSE 0 END) AS Q1,
SUM(CASE WHEN Quarter(DateOfPurchase) = 2 THEN 1 ELSE 0 END) AS Q2,
SUM(CASE WHEN Quarter(DateOfPurchase) = 3 THEN 1 ELSE 0 END) AS Q3,
SUM(CASE WHEN Quarter(DateOfPurchase) = 4 THEN 1 ELSE 0 END) AS Q4
FROM Purchases
GROUP BY SongID;
See SQL Fiddle with Demo
You can do this quarterly report easily using MySQL Pivot table generator.
While creating your report, you will be asked to add the "Column settings "
Please choose the "Purchasing table" as the "Table", the column that contains the date values as the "Field" . Once selecting a date value, a function menu should appear, please select "Quarter" to get your pivot table divided in quarters as you requested. please note that you have the option to create a report for one specific year if you like and in this case you should check the "Exact Year" Box and add a specific year otherwise leave the "Exact year" box unchecked .
The final report will be able to see something like this report :
http://mysqlpivottable.net/MySQL-Pivot-Table-Demo/tables/Quarterly_Sales_Report/

MySQL multiple count in single query

I have a table named 'sales' with following fields
salesid (type: int)
stime (type: datetime)
status (type: enum, values: remaining OR cancelled OR done)
... and other fields
I need a query that can output as
SalesDate TotalSales TotalDone TotalRemaining TotalCancelled
2010-11-06 10 5 3 2
2010-11-06 15 14 1 0
Anyone know how to achieve this?
Help appreciated, thanks.
You can use conditional summation to get the results you want.
select stime as sales_date
,sum(1) as total_sales
,sum(case when status = 'remaining' then 1 else 0 end) as total_done
,sum(case when status = 'cancelled' then 1 else 0 end) as total_remaining
,sum(case when status = 'done' then 1 else 0 end) as total_cancelled
from sales
group by stime;
You can also use COUNT(expr) and exploit the fact it doesn't include NULLS, but personally I find that the above best conveys the intent of the developer.
Use a CASE statement in your SELECT to create pseudo columns using the status values of remaining, cancelled and done
SELECT
date(stime),
COUNT(salesid),
SUM(CASE status WHEN 'done' THEN 1 ELSE 0 END) as TotalDone,
SUM(CASE status WHEN 'remaining' THEN 1 ELSE 0 END) as TotalRemaining,
SUM(CASE status WHEN 'cancelled' THEN 1 ELSE 0 END) as TotalCancelled
FROM sales
GROUP BY date(stime)
Note: This is what i was trying to refer to. I think this should work but i have no access to MySQL to try out the syntax and verify it. Sorry about that. But this should get you going.