Fetch how many failure and success did each person (name) have - mysql

I have a table buggy, the dummy dataset link can be see here
https://github.com/FirzaCank/Project/blob/main/SQL/IFG%20test/Dataset%20Dummy%20no%205.sql
Which contains:
id (INT)
name (VARCHAR)
bug (INT, contains the numbers 0 and 1)
With dataset explanations on 'bug' column are:
0, it means fault / failure
1, it means success
If there is no 'fault', then the 'fault' value will be filled with '0' (null is okay too), so is 'success'
I've tried a MySQL query like this:
SELECT name,
CASE
WHEN bug = 0 THEN COUNT(bug)
END AS failure,
CASE
WHEN bug = 1 THEN COUNT(bug)
END AS success
FROM buggy
GROUP BY name;
The desire output is like This, but as far as I've tried in the above syntax it just came out like this
Thank you for the help!

You should use SUM instead of Count.
SELECT
name,
SUM(IF(bug = 0, 1, 0)) as fault,
SUM(IF(bug = 1, 1, 0)) as success
FROM buggy
GROUP BY name
This counts the number of rows satisfying the conditions inside the IF function.

this sql will give wanted result
SELECT t.name , SUM(t.failure) as failure , SUM(t.success) as success
from ( SELECT name , CASE
WHEN bug < 1 THEN COUNT(bug) ELSE 0
END AS failure,
CASE
WHEN bug = 1 THEN COUNT(bug) ELSE 0
END AS success
FROM buggy
GROUP BY name,bug ) t
GROUP BY t.name;

Related

MySQL Case function behave strange and inconstent

We are using MySQL 8 as our java application DB.
We have a query with the following format:
select
id,
group_concat(NAME ORDER BY ID separator ',,') AS Code,
CASE
WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END AS factor
from MA_TABLE
join TABLE_P p on (...)
join TABLE_I i on (...)
group by id
The query worked very fine in our development environments until deploy with client where the factor column is getting null.
We have run the same query in the client environment from MySQL Workbench and we can see that the factor column is getting well populated.
After some debugging,we changed :
CASE
WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END AS factor
to
MAX(
WHEN p.VARIABLEfactor = 1 THEN i.factor ELSE p.factor END ) AS factor,
and the query worked correctly.
Any help here please?
From your explanation I gather that you don't understand the difference of your two case expressions. But they are very different. Let's look at an example for one ID:
ID
VARIABLEfactor
i.factor
p.factor
100
0
null
10
100
1
null
20
Your expression
CASE WHEN MAX(p.VARIABLEfactor) = 1 THEN MAX(i.factor) ELSE MAX(p.factor) END
looks at the maximum VARIABLEfactor, which is 1, so the THEN case applies and the maximum i.factor is returned. This is null, as all i.factor are null.
Your expression
MAX(WHEN p.VARIABLEfactor = 1 THEN i.factor ELSE p.factor END)
looks at each row's VARIABLEfactor. For the first row this is 0, so the ELSE case applies and p.factor 10 is used. For the second row the VARIABLEfactor is 1, so its i.factor null gets used. Of these you take the maximum, which is 10.
To recap: The first expression is just a CASE expression on the aggregation results. It returns null here. The second expression is a conditional aggregation. It returns 10 for the sample data.

Advanced (probably not?) MYSQL query select statement

Please see the below sample data:
'messages' table data:
id, date, user, seen
674, 1399430687, 2, 0
675, 1399430957, 2, 1399431766
676, 1399431065, 1, 1399431766
677, 1399431723, 2, 1399431766
678, 1399434322, 2, 0
679, 1399434330, 2, 0
I want to do a count of only the most recent non seen (seen=0) records to a particular user (user: 2) UP and ONLY UNTIL the next seen record (seen>0). So in the above case there are 3 unseen (seen=0) records to user (user: 2) but only 2 of them I am interested as the next 1 has some seen records in between it. So in the above scenario count of 2 would be returned (not the actual records).
Also if the most recent record to user (user: 2) is seen (seen>0) then count of 0 should be returned. I just can't get my head around how to do this in mysql, or how to really describe it.
This is all I can work out, but in the above scenario this will result in 3, not 2:
SELECT COUNT( * )
FROM `messages`
WHERE seen = 0
AND user = 2
ORDER BY DATE DESC
I hope this makes sense.
Thanks.
You need to find the latest non-zero seen data, and then filter after that.
SELECT Count(id) FROM data WHERE user = 3 AND seen = 0
AND date > (
SELECT coalesce(MAX(date),0) FROM data WHERE seen <> 0 AND user = 3
);
here's the fiddle
EDIT:
The previous code wouldn't return a correct answer if the user hadn't seen any records yet at all, this code fixes it by returning 0 instead of null.

MAX with extra criteria

I have the following part of a query I'm working on in MYSQL.
SELECT
MAX(CAST(MatchPlayerBatting.BatRuns AS SIGNED)) AS HighestScore
FROM
MatchPlayerBatting
It returns the correct result. However there is another column I need it to work off.
That is if the maximum value it finds also has a value of "not out" within "BatHowOut", it should show the result as for example 96* rather than just 96.
How could this be done?
To help make the data concrete, consider two cases:
BatRuns BatHowOut
96 not out
96 lbw
BatRuns BatHowOut
96 not out
102 lbw
For the first data, the answer should be '96*'; for the second, '102'.
You can achieve this using self-join like this:
SELECT t1.ID
, CONCAT(t1.BatRuns,
CASE WHEN t1.BatHowOut = 'Not Out' THEN '*' ELSE '' END
) AS HighScore
FROM MatchPlayerBatting t1
JOIN
(
SELECT MAX(BatRuns) AS HighestScore
FROM MatchPlayerBatting
) t2
ON t1.BatRuns = t2.HighestScore
See this sample SQLFiddle with highest "Not Out"
See this another sample SQLFiddle with highest "Out"
See this another sample SQLFiddle with two highest scores
How about ordering the scores in descending order and selecting only the first record?
select concat(BatRuns , case when BatHowOut = 'not out' then '*' else '' end)
from mytable
order by cast(BatRuns as signed) desc,
(case when BatHowOut = 'not out' then 1 else 2 end)
limit 1;
Sample here.
If you want to find highest score score for each player, here is a solution that may not be elegant, but quite effective.
select PlayerID,
case when runs != round(runs)
then concat(round(runs),'*')
else
round(runs)
end highest_score
from (select PlayerID,
max(cast(BatRuns as decimal) +
case when BatHowOut = 'not out' then 0.1 else 0 end
) runs
from MatchPlayerBatting
group by PlayerID) max_runs;
This takes advantage of the fact that, runs can never be fractions, only whole numbers. When there is a tie for highest score and one of them is unbeaten,
adding 0.1 to the unbeaten score will make it the highest. This can be later removed and concatenated with *.
Sample here.

mysql query question on count

SELECT if((COUNT(vote=1)-COUNT(vote=0) > 0,1,count(groupid))
FROM sample WHERE uid = $uid GROUP BY groupid
In the if statement, I was wondering if there is any simple way to achieve this: COUNT(vote=1)-COUNT(vote=0) > 0
Use SUM instead of COUNT:
SELECT if((SUM(vote=1)-SUM(vote=0) > 0,1,count(groupid))
FROM sample WHERE uid = $uid GROUP BY groupid
You want the sum of vote, except 0 counts as -1:
SELECT if(sum(if(vote, 1, -1)) > 0, 1, count(groupid))
...
are you trying to do
Select columns,
case when (COUNT(vote=1) - COUNT(vote=0)) > 0
then 'something'
else 'something else' as foo
From Sample
Where uid=$uid
Group By groupid
I don't quite understand what you are trying to achieve.
With my example, you select the columns (or just that case), when the difference is greater than 0. If it is greater show 'something' else show 'something else'
although, i don't have a way to test it on this computer, but maybe it will lead you or someone else in the right direction.

MySQL Query: count entries by status

I have a log table with following schema:
OperatorId - JobId - Status ( Good/Bad/Ugly )
Alex 6 Good
Alex 7 Good
James 6 Bad
Description: Whenever an operator works on a job, an entry is made along with Status. That's it.
Now I need a report like:
OperatorId - Good Count - Bad Count - Ugly Count
Alex 2 0 0
James 0 1 0
select operatorid,
sum(if(status="good",1,0)) as good,
sum(if(status="bad",1,0)) as bad,
sum(if(status="ugly",1,0)) as ugly
from table
group by operatorid
This is called a Pivot Table. It is done by setting a value 1 or 0 for each state and then summing them up:
SELECT
T.OperatorId,
SUM(T.GoodStat) AS Good,
SUM(T.BadStat) AS Bad,
SUM(T.UglyStat) AS Ugly
FROM
(
SELECT
CASE WHEN Status = 'Good' THEN 1 ELSE 0 END AS GoodStat,
CASE WHEN Status = 'Bad' THEN 1 ELSE 0 END AS BadStat,
CASE WHEN Status = 'Ugly' THEN 1 ELSE 0 END AS UglyStat,
OperatorId
FROM logTable T
)
GROUP BY T.OperatorId
If, like me, you prefer, whenever possible, to calculate counts with COUNT rather than with SUM, here's an alternative solution, which uses a method asked about in this thread:
SELECT
operatorid,
COUNT(status = 'good' OR NULL) as good,
COUNT(status = 'bad' OR NULL) as bad,
COUNT(status = 'ugly' OR NULL) as ugly
FROM table
GROUP BY operatorid