Reputation: 4886
I have a Statistics
table as give below
parent key value date
MASTER maths 400 2016-10-12
MASTER maths 200 2016-10-20
MASTER maths 350 2016-10-23
MASTER passed 20% 2016-10-25
MASTER passed 40% 2016-10-27
MASTER passed 30% 2016-10-28
MASTER maths 500 2016-11-12
MASTER maths 250 2016-11-20
MASTER maths 600 2016-11-23
MASTER passed 55% 2016-11-25
MASTER passed 75% 2016-11-27
MASTER maths 500 2016-12-12
MASTER maths 250 2016-12-20
MASTER maths 600 2016-12-23
MASTER passed 70% 2016-12-25
MASTER passed 65% 2016-12-26
MASTER passed 45% 2016-12-27
MASTER maths 500 2017-01-12
MASTER maths 450 2017-01-20
MASTER maths 770 2017-01-23
MASTER passed 87% 2017-01-25
MASTER passed 54% 2017-01-27
MASTER maths 900 2017-02-12
MASTER maths 250 2017-02-20
MASTER maths 500 2017-02-23
MASTER passed 67% 2017-02-25
MASTER passed 45% 2017-02-27
I got a requirement to bring up an output like as shown below using mysql
maths passed date
950 30% 2016-10
1350 65% 2016-11
1350 60% 2016-12
1720 70.5% 2017-01
1650 56% 2017-02
My Query which I have wrote is given below
SELECT SUM(CASE WHEN key = 'maths' THEN value ELSE 0 END) AS maths,
SUM(CASE WHEN key = 'passed' THEN value ELSE 0 END) AS passed
FROM Statistics
WHERE parent = 'MASTER' GROUP BY MONTH(date) ORDER BY date ASC
But I am the sum of passed instead of the average, that is lets say if I get 20%, 40% and 30% then I should get the average as 30% but for my above query I am getting 90%. Also the % is also disappeared in the result
Can anyone please help me on this
Upvotes: 0
Views: 768
Reputation: 24012
You have to use AVG
aggregate function for average
.
Change:
SUM(CASE WHEN key = 'passed' THEN value ELSE 0 END) AS passed
TO:
AVG(CASE WHEN key = 'passed' THEN value ELSE 0 END) AS passed
% symbols is removed
When an operator is used with operands of different types, type conversion occurs to make the operands compatible. Some conversions occur implicitly. For example, MySQL automatically converts numbers to strings as necessary, and vice versa.
To get the %
symbol displayed, you can contact it with results.
Following change in your query, may help you getting the desired results.
mysql> SELECT DATE_FORMAT( `date`, '%Y-%m' ) AS `month`
-> , SUM( CASE `key` WHEN 'maths' THEN `value` ELSE NULL END ) AS `maths`
-> -- , SUM( CASE `key` WHEN 'passed' THEN `value` ELSE NULL END ) AS `passed`
-> , CONCAT( ROUND( AVG( CASE `key` WHEN 'passed' THEN `value` ELSE NULL END ), 2 ), '%' ) AS `passedAvg`
-> FROM Statistics
-> WHERE parent = 'MASTER'
-> GROUP BY MONTH(`date`)
-> ORDER BY `date` ASC;
Results can be like this:
+---------+-------+-----------+
| month | maths | passedAvg |
+---------+-------+-----------+
| 2016-10 | 950 | 30.00% |
| 2016-11 | 1350 | 65.00% |
| 2016-12 | 1350 | 60.00% |
| 2017-01 | 1720 | 70.50% |
| 2017-02 | 1650 | 56.00% |
+---------+-------+-----------+
Documentation Reference:
Upvotes: 1
Reputation: 10827
Use a subquery:
To calculate AVG, first need to know how many rows has 'passed' values.
(Check it here.)
select yr as `year`, mt as `month`,
sum(val_maths) as `math`,
concat(cast((sum(val_passed) / sum(count_passed)) as char(50)), '%') as `passed`
from (
select ky, year(dt) as yr, month(dt) as mt,
if (ky = 'maths', replace(val,'%',''), 0) val_maths,
if (ky = 'passed', replace(val,'%',''), 0) val_passed,
if (ky = 'passed', 1, 0) as count_passed
from foot
) tv
group by yr, mt
;
| year | month | maths | passed |
|-------|-------|--------|--------|
| 2016 | 10 | 950 | 30% |
| 2016 | 11 | 1350 | 65% |
| 2016 | 12 | 1350 | 60% |
| 2017 | 1 | 1720 | 70.5% |
| 2017 | 2 | 1650 | 56% |
Upvotes: 1