How to change the value of sum function inside the query? - mysql

I have a query with sum aggregation function :
SELECT sum(case when result=1 then 1 when result=2 then 0)as final_result From results
I want to change this part when result=2 then 0 to something like that when result=2 then final_result equals zero
Is it possible to do this ? or there is another way for that?

Try this :
SELECT CASE WHEN cnt=sum THEN sum ELSE 0 END as Final_result
FROM
(
SELECT count(*) as cnt,
SUM(case when result=1 then 1 else 0 end) as sum
from results
) Temp
Working Fiddle here.
Explanation:
Inner query select the total number of records and the sum of the records. Then if those count and sum are equal that means all values are 1.
NB: Removed the checking when result=2 then 0 because, the query will select 0 for any values other than 1. So there is no need to check for result=2.
EDIT:
To find the count of 10 consecutive 1's, you can do:
SELECT SUM(CASE WHEN RN=10 THEN 1 ELSE 0 END) AS final_result
FROM
(
SELECT CASE WHEN result=1 THEN #row_number:=#row_number+1 ELSE #row_number:=0 END AS RN,
result
FROM results, (SELECT #row_number:=0) AS t
) Temp
Sample Fiddle here.

I think you want something like this:
SELECT case max(case result when 2 then 1 else 0 end)
when 1 then 0
else sum(case when result=1 then 1 else 0 end)
end as final_result
From results
Fiddle here
So what I'm doing is checking for the final-result-must-be-0 condition inside a MAX(). That way, if any of the rows meets this condition (i.e. result = 2), the maximum value will be 1. Then I can use that value to determine whether I wanna return 0 or do the SUM().

Related

MySQL : using sum in( case when ) statement shows 0 as result

new to MySQL..so pls help me out with this basic code..
i have a query something like this...
select weekofyear(id_time),
(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
and it gives correct results as--here
however i want to use sum after case when statement so that I can get total values where BO=1 and group by week of year , so i made following changes-
select weekofyear(id_time),
count(id),
#Tat1:=exp1,
#Tat2:=exp2,
#check1:=exp3,
#check2:=exp4,
sum(case when #check2=0 then
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+10))) then 1 else 0 end)
else
(case when (#Tat1>(#Tat2+30) or (#check1=1 and (#Tat1>#Tat2+20))) then 1 else 0 end)
end) as BO
from datb
where cid=18
and id_time between '2019-11-01 06:00:00' and '2019-11-25 06:00:00'
group by weekofyear(id_time)
but it always returns 0 as output.
Output --here 2
Please help , I don't know what am I doing wrong here.
Thanx !
As others have already said, session variables can be unpredictable (especially when aggregation gets mixed in). That said, it doesn't look like you're using the session variables to carry over values from one row to the next (as is often done), but to just make aliases of sorts for calculations you don't want to repeat.
A better way to handle that is just through subqueries.
SELECT woy, id, Tat1, Tat2, check1, check2
, CASE
WHEN check2=0 THEN (
CASE
WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+10))) THEN 1
ELSE 0
END
)
ELSE (
CASE WHEN (Tat1>(Tat2+30) OR (check1=1 AND (Tat1>Tat2+20))) THEN 1
ELSE 0
END
)
END AS BO
FROM (
SELECT WEEKOFYEAR(id_time) AS woy
, id
, exp1 AS Tat1
, exp2 AS Tat2
, exp3 AS check1
, exp4 AS check2
FROM datb
WHERE cid=18
AND id_time BETWEEN '2019-11-01 06:00:00' AND '2019-11-25 06:00:00'
) AS subQ
;
You can then tweak the above query for aggregation, or use it as a subquery for an aggregating outer query.

How to get count of columns using single queries

I have a table in my database from which i want to fetch data on the basis of count
my table name is syncbill and columns are Cancelled and Noofprints i am trying to write a query to fetch the count of cancelled and count of noofbills using single query
For cancelled i want to fetch count of cancelled where cancelled<>Y
for Noofprints i want to fetch count of noofprints where noofprints>1
I am using
select count(CANCELLED) as canceledbill,count(NOOFPRINTS) as duplicatebill
from syncbill where CANCELLED<>'Y' and NOOFPRINTS>1`
this query but it is giving me the same no of counts for both
any one out-here please guide me
you can use sum() with case expreseeion
SELECT
sum(CASE WHEN CANCELLED <> 'Y' THEN 1 else 0 END) AS canceledbill,
sum(CASE WHEN NOOFPRINTS > 1 THEN 1 else 0 END) AS duplicatebill
FROM table_name;
Use conditional aggregation:
SELECT
COUNT(CASE WHEN CANCELLED <> 'Y' THEN 1 END) AS cancelledbill,
COUNT(CASE WHEN NOOFPRINTS > 1 THEN 1 END) AS duplicatebill
FROM yourTable;
If you are actually using MySQL, then the above can be simplified to this:
SELECT
SUM(CANCELLED <> 'Y') AS cancelledbill,
SUM(NOOFPRINTS > 1) AS duplicatebill
FROM yourTable;
USE CASE WHEN Expression
select
sum(case when CANCELLED <> 'Y' then 1 else 0 end) AS cancelledbill,
sum(case when NOOFPRINTS > 1 then 1 else 0 end) AS duplicatebill
FROM tablename;

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

MYSQL - Showing status input as it's own column

I'm having trouble writing a SQL query to show the status of a row as it's own column as shown in the picture.
I was thinking of using an alias for Status as:
SELECT 'Table A.Date', 'Table A.Status' as ... FROM Table A;
But this doesn't resolve the issue on how to display each status type as their own column and number value.
Can someone point out how to do this?
Try this one. I used CASE statement to conditionally count the status as one depending on the status type given.
SELECT
Date,
SUM(CASE WHEN Status='Pending' THEN 1 ELSE 0 END)Pending,
SUM(CASE WHEN Status='Completed' THEN 1 ELSE 0 END)Completed,
SUM(CASE WHEN Status='Cancelled' THEN 1 ELSE 0 END)Cancelled
FROM Table A
WHERE Date='2014-01-01'
GROUP BY Date
Try this:
select A.date,
count(
case
when A.Status='Pending'
Then 1
Else NULL
End
) as Pending,
count(
case
when A.Status='Completed'
Then 1
Else NULL
End
) as Completed,
count(
case
when A.Status='Cancelled'
Then 1
Else NULL
End
) as Cancelled
From A
group by A.date

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.