How to get multiple SUM with one SQL query? - mysql

I am wondering how to fix this query.
SELECT
SUM(`month_using`) used,
SUM(`month_cash`) paycash,
SUM(`month_profit` CASE WHEN `id` <> 'system' THEN 1 ELSE 0 END) profit
FROM `_using_month`
WHERE MONTH(`month_date`) = {month} AND YEAR(`month_date`) = {year}
Thanks

Use Group by clause to get multiple SUM:
For Example:
SELECT YEAR(month_date), MONTH(month_date),
SUM(month_using) used, SUM(month_cash) paycash,
SUM(month_profit CASE WHEN id <> 'system' THEN 1 ELSE 0 END) profit
FROM _using_month
GROUP BY YEAR(month_date), MONTH(month_date)

Related

Filtering MySQL output without referencing alias but where SUM(CASE) is used

With a view to remediating missing userIDs in our database, I'm trying to look at instances where - within the same table, the same user is found with and without IDs. So far, I have a rough result using the following:
SELECT users,
SUM(CASE WHEN UserID = "" THEN 1 ELSE 0 END) as InstancesWithoutIDs,
SUM(CASE WHEN UserID <> "" THEN 1 ELSE 0 END) as InstancesWithIDs,
COUNT(*) as TOTAL
FROM table.users
GROUP BY name;
I would now like a where InstancesWithIDs > 0 filter applied to the table. But as I keep reading, I can't reference an alias in the filter. From googling around, I think the best I've gotten is:
SELECT * from (
SELECT users,
SUM(CASE WHEN UserID = "" THEN 1 ELSE 0 END) as InstancesWithoutIDs,
SUM(CASE WHEN UserID <> "" THEN 1 ELSE 0 END) as InstancesWithIDs,
COUNT(*) as TOTAL
FROM table.users) A
where InstancesWithIDs > 0;
But this then displays all results as a single record.
users || InstancesWithoutIDs || InstancesWithIDs
A. Fisher 62588 947711
How can I get the full table displayed, as I did with the top query?
Any help much appreciated!!
You can use Having (only when you use GROUP BY) like this:
SELECT users,
SUM(CASE WHEN UserID = "" THEN 1 ELSE 0 END) as InstancesWithoutIDs,
SUM(CASE WHEN UserID <> "" THEN 1 ELSE 0 END) as InstancesWithIDs,
COUNT(*) as TOTAL
FROM table.users
GROUP BY name
HAVING InstancesWithIDs > 0;
HAVING would be the equivalent to WHERE but for aggregated functions

Difference between these two mysql queries

I want to know the difference between these two queries: The first query is giving me all the records and its just fine.
Select * from table1 where tender_id='$tender_id' group by supplier_name
But in the following query I have added a sum(case), but I am not getting the desired output. The first query is showing all the records, but the second query is not showing all the records. What mistake am I making?
select cs.*, tender_id,
SUM(CASE WHEN ifmain = 'Yes' THEN total_inr ELSE 0 END) AS maintotal,
SUM(CASE WHEN ifmain = 'No' THEN total_inr ELSE 0 END) AS subtotal
from table1 cs
where cs.tender_id='$tender_id'
group by cs.supplier_name
I want to know if the second query can display all the records with conditions (tender_id)? or its iterating more?
In standard SQL, a query that includes a GROUP BY clause cannot refer
to nonaggregated columns in the select list that are not named in the
GROUP BY clause.
see (for example) https://dev.mysql.com/doc/refman/5.0/en/group-by-handling.html
MySQL has a an unfortunate (and in my opinion incorrect) default behavior when using a GROUP BY clause. This query would NOT be valid in most SQL databases:
Select * from table1 where tender_id='$tender_id' group by supplier_name
and it would not be valid in MySQL either if the ONLY_FULL_GROUP_BY SQL mode has been enabled.
I strongly recommend you treat all queries using GROUP BY as needing ALL non-aggregating columns in that clause. e.g.
select
cs.supplier_name
, SUM(CASE WHEN ifmain = 'Yes' THEN total_inr ELSE 0 END) AS maintotal
, SUM(CASE WHEN ifmain = 'No' THEN total_inr ELSE 0 END) AS subtotal
from table1 cs
where cs.tender_id='$tender_id'
group by
cs.supplier_name
If you need extra columns then e.g.
select
cs.supplier_name
, tender_id
, SUM(CASE WHEN ifmain = 'Yes' THEN total_inr ELSE 0 END) AS maintotal
, SUM(CASE WHEN ifmain = 'No' THEN total_inr ELSE 0 END) AS subtotal
from table1 cs
where cs.tender_id='$tender_id'
group by
cs.supplier_name
, tender_id
and so on. Of course as you include more columns in the group by clause you may increase the number of rows produced, but that is how GROUP BY should work.

Reduce the number of queries

I have seperate queries but i need to reduce the no so put all in one
select count(applicant_id) as registered from student_application where filter_status=0 AND
select count(applicant_id) as filer_select from student_application where filter_status=1 AND
select count(applicant_id) as filter_reject from student_application where filter_status=2
but this shows some errors
Use CASE expression.
Query
select
count(case when filter_status = 0 then applicant_id else null end) as registered,
count(case when filter_status = 1 then applicant_id else null end) as filer_select,
count(case when filter_status = 2 then applicant_id else null end) as filer_reject
from student_application;
SQL Fiddle
You could also use group_by, with the where clause if you're looking for a subset rather than all possible values of filter_status:
SELECT filter_status, COUNT(*)
FROM student_application
WHERE filter_status in (0, 1, 2)
GROUP BY filter_status;

MySQL sum on condition does not work in a view

In MySQL (v5.5), the value of numNotCast, numInFavor is always 0 when selecting all rows of the view. If the select statement is executed alone (not in the view), it works as expected returning the correct count of the the number of rows in the vote column equal to value 'notcast' and 'infavor'.
CREATE OR REPLACE
VIEW `Stats` AS
select
sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`,
sum(case when `p`.`vote` = 'infavor' then 1 else 0 end) AS `numInFavor`
from
(`Debate` `d`
join `Participant` `p` ON ((`d`.`debateId` = `p`.`debateId`)))
group by `d`.`debateId`
Is this a limitation on MySQL views? How do you accomplish this conditional summing function in the view?
Then your statement is correct as SQLFiddle confirms, so your problem is probably somewhere else
CREATE OR REPLACE VIEW Stats AS
select
Debate.debateId,
sum(case when Participant.vote='notcast' then 1 else 0 end) as numNotCast,
sum(case when Participant.vote='infavor' then 1 else 0 end) as numInFavor
from
Debate
inner join
Participant on Participant.debateId = Debate.debateId
group by
Debate.debateId
Updated after the clarification
There are many limitations in MySQL views, but I don't think this is one of them.
I think it is strange that the name of the view is in single quotes. That might be allowed, but the view may not be doing what you want. Try this:
CREATE OR REPLACE VIEW `Stats` AS
select sum(case when `p`.`vote` = 'notcast' then 1 else 0 end) AS `numNotCast`
from `Debate` `d` join
`Participant` `p`
ON `d`.`debateId` = `p`.`debateId`
group by `d`.`debateId`;
By the way, in MySQL, you can simplify the select to:
select sum(p.vote = 'notcast') as numNotCast

get count of two table fields in one query

I am trying to get the count of females and males in the gender field of a table.
Is there a way to get the count of each in one query?
Something like:
select * from table count(where gender = 'm') as total_males, count(where gender = 'f') as total_females;
or will it require two queries?
select count(*) from table where gender = 'm';
select count(*) from table where gender = 'f';
This is basically a PIVOT. MySQL does not have a pivot so you can use an aggregate function with a CASE statement to perform this:
select
sum(case when gender = 'm' then 1 else 0 end) Total_Male,
sum(case when gender = 'f' then 1 else 0 end) Total_Female
from yourtable
See SQL Fiddle with Demo
Or using COUNT:
select
count(case when gender = 'm' then 1 else null end) Total_Male,
count(case when gender = 'f' then 1 else null end) Total_Female
from yourtable;
See SQL Fiddle with Demo
Something like this will work:
SELECT SUM(IF(t.gender='m',1,0)) AS total_males
, SUM(IF(t.gender='f',1,0)) AS total_females
FROM mytable t
The "trick" here is that we are using a conditional test to return either a 0 or a 1 for each row, and then adding up the 0's and 1's. To make this a little more clear, I am using the SUM aggregate function rather than COUNT, although COUNT could be used just as easily, though we'd need to return a NULL in place of the zero.
SELECT COUNT(IF(t.gender='m',1,NULL)) AS total_males
, COUNT(IF(t.gender='f',1,NULL)) AS total_females
FROM mytable t
Consider that the two expressions in the SELECT list of this query:
SELECT COUNT(1)
, SUM(1)
FROM mytable t
Will return the same value.
If you want to avoid the MySQL IF function, this can also be done using the ANSI SQL CASE expression:
SELECT SUM( CASE WHEN t.gender = 'm' THEN 1 ELSE 0 END )) AS total_males
, SUM( CASE WHEN t.gender = 'f' THEN 1 ELSE 0 END )) AS total_females
FROM mytable t
select sum(case when gender='m' then 1 else null end) as total_males, sum(case when gender='f' then 1 else null end) as total_females from ...
Should work just fine!
If your only issue is to avoid two queries, you can always write two queries as subselects of one query.
Select (select 1 from dual) as one, (select 2 from dual) as two from dual
This would work for your scenario, too.