I am using a MySQL database and I have a big mysql_query that works completely fine except for this one line.
SELECT game_id,
COALESCE(
SUM(CASE WHEN game_score = 1 THEN 1 ELSE 0 END)
-
SUM(CASE WHEN game_score = 0 THEN 1 ELSE 0 END), 0) AS score
FROM ....
WHERE ....
GROUP BY ....
This line returns me almost all of the numbers that I want, yet they are the same numbers as when I wasn't using the COALESCE function.
I would like this statement to return me 0 when there is a game_id that has an emptygame_score` field.
Where is my code going wrong?
you can also use decode function like this ---
SELECT game_id,
SUM(DECODE(game_score, null, 0, 0, -1, 1, 0)) AS score
FROM ....
WHERE ....
GROUP BY ....
I have checked this query for working, its fine
hope it helps you....
add
when game_score is null then ...
Edit
SELECT game_id, case when game_score is null then 0 else
SUM(CASE WHEN game_score = 1 THEN 1 ELSE 0 END)
-
SUM(CASE WHEN game_score = 0 THEN 1 ELSE 0 END) end AS score
FROM games
group by ...
See this SQLFiddle Example
Use is null like
CASE WHEN game_score = 1 THEN 1
when game_score is null THEN 0
ELSE 0 END
The problem is that game_id can have an empty game_score field in one row and a valid one in another. Your code picks up the valid one and returns non-null.
Fix this problem by looking for this case explicitly, as the first argument to coalesce:
SELECT game_id,
(CASE WHEN count(*) <> count(game_score) then NULL
ELSE COALESCE(SUM(CASE WHEN game_score = 1 THEN 1 ELSE 0 END),
. . .
I'm not sure what the coalesce is trying to do. It seems to be adding one for a bunch of different game_scores. Can you use one of the following instead:
COUNT(game_score) ?
SUM(case when game_score between 1 and xx then 1 else 0 end) ?
Use the COALESCE function around your field name in your statements instead of surrounding the SUM function:
SUM(CASE COALESCE(game_score,0) WHEN 1 THEN 1 ELSE 0 END) - SUM(CASE COALESCE(game_score,0) WHEN 0 THEN 1 ELSE 0 END)
Related
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.
I am new in sql. I want to count something like:
Select count(*) from table where col1= x and col2=x and Col3=x.
I need to count the same value in all different column.
Any help will be appreciated.
You can use conditional aggregation :
Select sum(case when col1='x' then 1 else 0 end) as count_col1,
sum(case when col2='x' then 1 else 0 end) as count_col2,
sum(case when col3='x' then 1 else 0 end) as count_col3
from tab;
If you want to have sum of these count values, consider the above query as an inner and use the following :
Select q.*,
q.count_col1 + q.count_col2 + q.count_col3 whole_sum
from
(
Select sum(case when col1='x' then 1 else 0 end) as count_col1,
sum(case when col2='x' then 1 else 0 end) as count_col2,
sum(case when col3='x' then 1 else 0 end) as count_col3
from tab
) q
Rextester Demo
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
SELECT NAMA_DUN,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 0 then 1 else 0 end) AS FEMALE,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 1 then 1 else 0 end) AS MALE,
COUNT(DISTINCT(noMyKid)) as jumlah
FROM mohon
LEFT JOIN dun ON dun.KOD_DUN=mohon.dun_nama
WHERE status_proses = 'diproses'
AND concat('20', substr(noMyKid, 1, 2)) = '2008'
AND status_mohon = 'Layak'
AND status_semak = '1'
AND (
status_bayar = ''
OR status_bayar = 'Belum'
OR status_bayar = 'Sudah')
AND (
status_terima = ''
OR status_terima = 'Terima'
) GROUP BY dun_nama
ORDER BY NAMA_DUN
This is my mysql code. why is my 'COUNT CASE WHEN' give the same output for female and male column.
Usually COUNT() is used to count rows and is therefore very often used in the form COUNT(*). When you use a field (or anything else) as a parameter into the COUNT() it counts 1 for every no NULL value.
In your case all your values are not NULL (they are either 1 or 0) and consequently you end up with the same results.
So Abhik Chakraborty is right, use SUM() and everything should be fine.
The COUNT() function does only recognize non-null values, so when using case expressions such as you have here, you can explicitly return NULL where needed
SELECT NAMA_DUN,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 0 then 1 else NULL end) AS FEMALE,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 1 then 1 else NULL end) AS MALE,
COUNT(DISTINCT(noMyKid)) as jumlah
OR, implicitly return NULL by ignoring the else condition
SELECT NAMA_DUN,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 0 then 1 end) AS FEMALE,
COUNT(case when ((RIGHT(noMyKid, 1))% 2) = 1 then 1 end) AS MALE,
COUNT(DISTINCT(noMyKid)) as jumlah
OR, mimic the effect of count by using SUM() provided you do use 1 and 0 (or 1 and NULL)
SELECT NAMA_DUN,
SUM(case when ((RIGHT(noMyKid, 1))% 2) = 0 then 1 else 0 end) AS FEMALE,
SUM(case when ((RIGHT(noMyKid, 1))% 2) = 1 then 1 else 0 end) AS MALE,
COUNT(DISTINCT(noMyKid)) as jumlah
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.