Count numbers without Zero - mysql

I have a query who works correctly, but where I want to make a change.
The query counts all notes for id_service = 89.
The notes are numbers between 0 and 3 not more.
My query counts all those notes to get an Average.
All works fine.
The change what I want is, that he counts only the notes between 1 and 3 (not 0).
I don't know how I can do that.
Example:
This query count how much time I get the number 3 with all conditions.
Here the query:
SELECT round( avg( AVG =3 ) * count( AVG ) ) AS New
, sma_famille.famille
FROM (
SELECT ROUND( SUM( note ) / count( note ) ) AS AVG
, sma_famille.famille
, sma_agents.nom
FROM sma_notes
INNER JOIN sma_famille
ON sma_famille.id_service =89
INNER JOIN sma_agents
ON sma_notes.id_agent = sma_agents.id_agent
INNER JOIN sma_service_activite
ON sma_service_activite.id_activite = sma_notes.id_activite
AND sma_service_activite.id_famille = sma_famille.id_famille
AND sma_service_activite.id_service = sma_famille.id_service
GROUP BY sma_famille.famille, sma_agents.nom
) AS FN
LEFT JOIN sma_famille
ON sma_famille.id_service =89
AND FN.famille = sma_famille.famille
GROUP BY FN.famille
An example:
In Bio I can give 2 notes per persons like Bio Part1 and Bio Part2.
In my example I have two persons.
I give in Bio Part1 the note "3" for both and in Bio Part2 i don't give a note, so that there are the note "0"!
Here the result of my query:
That is what I get:
Note Math English Bio
1 0 0 0
2 0 0 2
3 0 0 0
That is what I want:
Note Math English Bio
1 0 0 0
2 0 0 0
3 0 0 2
Without the note "0" I must get an average of 100% for the note "3".
Now i get:
Note Math English Bio
1 0
2 0
3 2
And not
Note Math English Bio
1 0 0 0
2 0 0 0
3 0 0 2
How can i get the "0" in the resultset
Anybody an idea?

One way to get a count of values > 0 would be:
count(case when note > 0 then note end)
(Where note is 0, the case evaluates as null which is not counted.)
Although the simplest way might be
sum(sign(note))

Related

How to use count in sql based on a IF condition

From this table
groupId
flag
flagValue
1
0
500
2
0
100
1
1
10
2
1
50
3
0
100
1
1
200
3
1
1000
2
1
50
I need this result
groupId
flag1
flag0
valFlag1
valFlag0
totalFlags
1
2
1
210
500
3
2
2
1
100
100
3
3
1
1
1000
100
2
where
flag1 is number of times flag is 1 for a particular group
flag0 is number of times flag is 0 for a particular group
valFlag1 is sum of flagVal when flag is 1
valFlag0 is sum of flagVal when flag is 0
totalFlags is sum of total flags associated with a group
I am stuck as to how to actually count values based on an IF condition.
Anyhelp is appreciated. Thanks.
I have used a table named group_table with your values
Try using this:
SELECT
g.`groupId`,
SUM(g.`flag`=1 ) AS flag1,
SUM(g.`flag`=0) AS flag0,
SUM(CASE WHEN g.`flag`=1 THEN g.`flagValue` ELSE 0 END) AS valFalg1,
SUM(CASE WHEN g.`flag`=0 THEN g.`flagValue` ELSE 0 END) AS valFalg0,
COUNT(*) AS totalFlags
FROM
`group_table` g
GROUP BY g.`groupId`
If you have to use the IF,
SELECT
g.`groupId`,
IF(g.`flag`=1,1,0 ) AS flag1,
IF(g.`flag`=0,1,0) AS flag0,
SUM(IF(g.`flag`=1,g.`flagValue`,0 )) AS valFalg1,
SUM(IF(g.`flag`=0,g.`flagValue`,0 )) AS valFalg0,
COUNT(*) AS totalFlags
FROM
`group_table` g
GROUP BY g.`groupId`, flag1, flag0
They'll produce the same result

Sort Data in a Range MySQL

I have a table like below
SUBJECT - MARKS - SEMESTER
MATH - 50 - 1
SCIENCE - 60 - 1
ENGLISH - 70 - 1
MATH - 60 - 2
SCIENCE - 80 - 2
ENGLISH - 90 - 2
I want to produce a output like below. The problem is, even there is no data between 0-10 range I want 0 in all three columns. I am unable to achieve using "group by" and "sum". Do any of you have any idea
RANGE MATH SCIENCE ENGLISH
0-10 0 0 0
10-20 0 0 0
20-30 0 0 0
30-40 0 0 0
40-50 0 0 0
50-60 1 0 0
60-70 1 1 0
70-80 0 0 1
80-90 0 1 0
90-100 0 0 1
You can do this, but you need to define the ranges, either as a reference table or in the query. The rest is conditional aggregation:
select r.range,
sum(subject = 'MATH' and t.marks is not null) as Math,
sum(subject = 'SCIENCE' and t.marks is not null) as Science,
sum(subject = 'English' and t.marks is not null) as English
from ((select 0 as mins, 9.99 as maxs, '0-10' as range) union all
(select 10 as mins, 19.99 as maxs, '10-20' as range) union all
. . .
(select 90 as mins, 100 as maxs, '90-100' as range)
) left join
table t
on t.marks between r.mins and r.maxs
group by r.range
order by min(r.mins);

rows to column and vice-versa conversion

By running the following query I will get the result below. I want to convert this result into rows and whatever is there as row over ther those I want to convert into columns.
I want that project_level and account_level to come in rows and the remaining in rows goes to column.
SELECT S.Description,T.Project_Level,S.Account_Level FROM
(
SELECT DISTINCT SM.Description, COUNT(VA.FK_Status_ID) AS Project_Level,SM.Seq
From DeliveryPlatform_APPS.VA.DP_VA_Item_Status_Master SM
LEFT OUTER JOIN DeliveryPlatform_APPS.VA.DP_VA_Items VA ON SM.Status_ID = VA.FK_Status_ID
AND VA.FK_DP_Entity_Type_ID = 1 AND FK_DP_Entities=671
GROUP BY SM.Description,SM.Seq,FK_Status_ID
) AS T
INNER JOIN
(
SELECT DISTINCT SM.Description, COUNT(VA.FK_Status_ID) AS Account_Level,SM.Seq
From DeliveryPlatform_APPS.VA.DP_VA_Item_Status_Master SM
LEFT OUTER JOIN DeliveryPlatform_APPS.VA.DP_VA_Items VA ON SM.Status_ID = VA.FK_Status_ID
AND VA.FK_DP_Entity_Type_ID = 1 AND FK_DP_Entities=671
GROUP BY SM.Description,SM.Seq,FK_Status_ID
) AS S
ON S.Description=T.Description
--ORDER BY Seq
Description Project_Level Account_Level
Accepted 0 0
Closed 0 0
Delivered 0 0
Dropped 0 0
Open 0 0
Parked 0 0
Shortlisted 0 0
Work In Progress 0 0
You should check SQL Server PIVOT and UNPIVOT techniques to accomplish your intent:
http://msdn.microsoft.com/en-us/library/ms177410(v=sql.105).aspx

SQL query to group records under separate fields

I'm working with MySQL, and I have the following schema:
id school round score win loss tie
2 My School Name 1 10 1 0 0
3 My School Name 2 20 0 1 0
4 My School Name 3 30 1 0 0
5 My School Name 4 40 1 0 0
6 My School Name 5 50 1 0 0
7 My School Name 6 60 0 0 1
And I need the following output, grouped by school name
School Round1 Round2 Round3 Round4 Round5 Round6 wins losses ties
My School Name 10 20 30 40 50 60 4 1 1
So far I feel like I can use GROUP BY School and SUM(win) as wins to get most of the functionality out of it. The hard part, though, is to get those Round_ fields.
Does anyone know how to do this? Thanks in advance, any help would be much appreciated!
Edit: to clarify, I know I have 10 rounds exactly.
We can use a SELECT statement with a GROUP BY school to create a record for each school. The ties, wins, and losses columns are readily calculated with the SUM aggregate function, as you noted. To target a specific round, we can use some clever math (to avoid verbose conditional statements like the one CodeByMoonlight suggested):
If we want to target round R, we note that "round-R" is 0 only when round == R, otherwise it isn't 0. When we take the NOT of "round-R", 0 gets inverted to 1, while everything else gets set to 0. Now, if we multiply !(round-R) by the score of that round, it will give us 0 when the round is not R (as 0*score = 0) and it will give us "score" when the round is R (as 1*score = score). Next, when we take the SUM of this value over the columns, we add score when round=R and 0 otherwise, effectively giving us just the round R score.
Putting that all together gives:
SELECT school AS `School`,
SUM(!(round-1)*score) AS `Round1`,
SUM(!(round-2)*score) AS `Round2`,
SUM(!(round-3)*score) AS `Round3`,
SUM(!(round-4)*score) AS `Round4`,
SUM(!(round-5)*score) AS `Round5`,
SUM(!(round-6)*score) AS `Round6`,
SUM(!(round-7)*score) AS `Round7`,
SUM(!(round-8)*score) AS `Round8`,
SUM(!(round-9)*score) AS `Round9`,
SUM(!(round-10)*score) AS `Round10`,
SUM(win) AS `wins`,
SUM(loss) AS `losses`,
SUM(tie) AS `ties`
FROM `RoundScores` GROUP BY `school`
where RoundScores is the table in question.
EDIT:
If we do not want to manually add 10, we can use prepared statements :
# Store all the conditionals in a string:
# I was not able to to have round loop from 1 to 10, so I iterated over
# all distinct values of 'round' present in the table.
SET #s = "";
SELECT `round`, (#s := CONCAT( #s , "SUM(!(round-",round, ")*score) AS `Round",round, "`," )) FROM `RoundScores` GROUP BY `round`;
# Combine the conditionals from before with the rest of the statement needed.
SET #qry = CONCAT("SELECT school AS `School`,",#s,"SUM(win) AS `wins`,SUM(loss) AS `losses` FROM `RoundScores` GROUP BY `school`");
# Prepare and execute the statement.
PREPARE stmt1 FROM #qry;
EXECUTE stmt1;
TRY WITH UNION ( not tested)
SELECT SUM(win) AS wins, SUM(loss) AS losses, SUM(tie) AS ties
FROM table
GROUP BY (school)
UNION
SELECT score AS round1 FROM table WHERE round=1
UNION
SELECT score AS round2 FROM table WHERE round=2
.... AND so on..
SELECT School, Sum(Case
When Round = 1 Then Score
Else 0
End) AS Round1, Sum(Case
When Round = 2 Then Score
Else 0
End) AS Round2, Sum(Case
When Round = 3 Then Score
Else 0
End) AS Round3, Sum(Case
When Round = 4 Then Score
Else 0
End) AS Round4, Sum(Case
When Round = 5 Then Score
Else 0
End) AS Round5, Sum(Case
When Round = 6 Then Score
Else 0
End) AS Round6, Sum(Case
When Round = 7 Then Score
Else 0
End) AS Round7, Sum(Case
When Round = 8 Then Score
Else 0
End) AS Round8, Sum(Case
When Round = 9 Then Score
Else 0
End) AS Round9, Sum(Case
When Round = 10 Then Score
Else 0
End) AS Round10, Sum(Wins) AS Wins, Sum(Losses) AS Losses, Sum(Ties) AS Ties
FROM MyTable
GROUP BY School
Should work :)

MySQL query to count non-null values in a single row

I'm trying to put together a MYSQL query that will count the number of Non-Null (or better yet, non-zero) values in select fields in a single row and then sort from lowest to highest (based on the count). For example, I have a table with 5 fields... ID, Name, Score_1, Score_2, Score_3. I want to count how many times the value "0" exists in Score_1, Score_2 and Score_3 for each record, then sort from most non zero values to least.
ID Name Score_1 Score_2 Score_3
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
4 Mike 4 5 5
I assume the query has to look something like this...
Select ID, Name, Score_1, Score_2, Score_3 where (???) ORDER BY (???)
Output should look like this (ID 4 is displayed first since it has the least amount of non-zero entries)...
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
I'm somewhat new to mysql query's, so any help would be greatly appreciated. I thought the COUNT function would help, but that function appears to count columns from all rows. Perhaps there is a way to use the COUNT function and limit it to a singel row so it can be sorted by that row count?
This should do what you want:
SELECT ID, Name, Score_1, Score_2, Score_3
FROM Table1
ORDER BY (Score_1 = 0) + (Score_2 = 0) + (Score_3 = 0)
Result:
ID Name Score_1 Score_2 Score_3
4 Mike 4 5 5
1 Dan 8 7 0
2 Joe 0 0 3
3 Chris 0 0 0
try This:
Select id, Count1, Count2, Count3, Count4
From
(Select
Sum(Case When IsNull(Score_1,0) = 0 Then 1 Else 0 End) Count1,
Sum(Case When IsNull(Score_2,0) = 0 Then 1 Else 0 End) Count2,
Sum(Case When IsNull(Score_3,0) = 0 Then 1 Else 0 End) Count3,
Sum(Case When IsNull(Score_4,0) = 0 Then 1 Else 0 End) Count4
From Table
Group By Id) Z -- This column (Id) better not be the PK for this table!!!
Order By Count1 + Count2 + Count3 + Count4