使用MYSql

时间:2017-03-07 11:34:39

标签: mysql sum aggregate average

我有一个Statistics表,如下所示

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

我要求使用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

我写的我的查询在下面给出

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

但我是通过而不是平均值的总和,也就是说如果我得到 20%,40% 30%那么我应该得到平均值为 30%,但对于我上面的查询,我得到 90%也会在结果

中消失

任何人都可以帮助我

2 个答案:

答案 0 :(得分:1)

使用子查询:

要计算AVG,首先需要知道有多少行已经“传递”了值。

(检查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%    |

答案 1 :(得分:1)

您必须对AVG使用average聚合函数。

更改

SUM(CASE WHEN key = 'passed' THEN value ELSE 0 END) AS passed

AVG(CASE WHEN key = 'passed' THEN value ELSE 0 END) AS passed
  

%符号已删除

当运算符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。某些转换是隐式发生的。例如,MySQL会根据需要自动将数字转换为字符串,反之亦然。

要显示%符号,您可以将其与结果联系 在您的查询中进行更改后,可能会帮助您获得所需的结果。

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;

结果可以是这样的:

+---------+-------+-----------+
| 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%    |
+---------+-------+-----------+

文档参考

  • Type Conversion in Expression Evaluation
    • 当运算符与不同类型的操作数一起使用时,会发生类型转换以使操作数兼容。某些转换是隐式发生的。例如,MySQL会根据需要自动将数字转换为字符串,反之亦然