I have a sample table below and I am trying to get the number of student above the average score and number of students below the average score.
name subject classroom classarm session first_term_score first_term_grade std1 math nursery 1A nursery1 2018/2019 90 A std2 eng nursery 1A nursery1 2018/2019 70 A std3 sci nursery 1A nursery1 2018/2019 60 B std1 eng nursery 1A nursery1 2018/2019 64 B std2 math nursery 1A nursery1 2018/2019 70 A
The target result table is supposed to look like
subject avg_score count_above count_below math 80 1 1 eng 65.5 2 0
I have been able to write a query to get the names of students above the average score and this can be easily edited to get the count of students below the avg score.
SELECT name FROM (SELECT name, AVG(first_term_score) AS average_result FROM seveig GROUP BY name) sa, (SELECT (AVG(first_term_score)) tavg FROM seveig) ta WHERE sa.average_result > ta.tavg
The issue here is that I want to add the counts in a table indicating the number of students above and below the average score.
If a number is equal to the average score, it can be considered as above the average score.
Advertisement
Answer
If you are running MySQL 8.0, you can use window functions and aggregation:
select subject, avg_score, sum(first_term_score >= avg_score) count_above, sum(first_term_score < avg_score) count_below from ( select t.*, avg(first_term_score) over(partition by subject) avg_score from mytable t ) t group by subject, avg_score
In earlier versions, you can join the table with an aggregate query that computes the average score per subject:
select t.subject, a.avg_score, sum(t.first_term_score >= a.avg_score) count_above, sum(t.first_term_score < a.avg_score) count_below from mytable t inner join ( select subject, avg(first_term_score) avg_score from mytable group by subject ) a on a.subject = t.subject group by t.subject, a.avg_score
Edit: you appear to be running Big Query, not MySQL as initially tagged. You can use COUNTIF()
:
select subject, avg_score, countif(first_term_score >= avg_score) count_above, countif(first_term_score < avg_score) count_below from ( select t.*, avg(first_term_score) over(partition by subject) avg_score from mytable t ) t group by subject, avg_score