用过Excel的同学都知道,Excel很好用,无论你是在行方向还是列方向都可以调用系统给你的各种函数,并且你还可以自定义一个运算函数,这令处理数据变得更加快捷方便。而对于mysql呢,在下查找过很多的资料,看到的大多数是列方向上的运算,而对于行方向上的运算却少之又少。众所周知,统计学上的数据表,不单单是纵向,横向的运算也很重要。下面就让小弟来为大家讲解在mysql中,如何在列方向和行方向进行数据处理。如有不当之处,还望各位大佬不吝赐教。
1 sum,avg,min,max纵向横向运算
我们都知道sum,avg,min,max这四个基本函数是对数据表中的列进行相应的运算,他们对行方向的运算是不能够进行的。
首先我们要明确这个列方向的运算是什么方向的运算,比如sum,这个是对某列进行求和,avg是对某列进行平均,min,max分别是对某列分别求最小值,最大值。它这么做的目的在于,对于一张表来说,列向的数据属性都是一样的,具有相同的数据属性的数据才能够进行统计学上的各种运算。
1.1 基本的运算函数
>select sum(列名),avg(列名),min(列名),max(列名) from 表名;
对于如下这张表(为了方便而杜撰的,首字母没大写,“理综”用了拼音,请见谅):
图1. 数据表的属性
图2. 学生考试成绩单
图3. 进行求和,平均,最小,最大等运算的结果
上述的四种运算皆是对某列(列名分别为math, chinese, english, lizong)进行运算,都是对单列进行运算。那么如果相对两列进行运算呢,比如说我想看看的math,Chinese两科的平均分,这该怎么办呢?
1.2 两列之间的运算
我们首先看看,直接把两列相加的结果传给这四个函数。
图4. 两列相加
“math+Chinese”这个的含义是每个同学的数学和语文这两科成绩的总分。在这里,我们脑洞大开,摒弃这张表的具体含义,思考更长远的用法。既然两列可以加,那肯定两列也可以减,乘,除以及取余咯。是的,没错,确实可以这样:
图5. 拓展
可能大伙儿会疑惑,我这样计算了,但这个计算过程是什么样的呢?如果不知道它是怎么计算的,你这个计算那岂不是一点用都没有?接下来,我们来找找原因。
1.3 缘由
我们去除这四个函数,单独看看“+”、“-”、“*”、“/”、“%”这五种运算是怎么回事。
图6. 加减乘除取余等五个运算
从这里可以看出,运算结果有五行,而我们的原始数据表也有五行,这说明不单单sum,avg,min,max这四个函数是对列进行的运算,连“+”、“-”、“*”、“/”、“%”这五个运算都是对列方向进行的运算。大家也可以去验证这个结果,这里的加减法跟数学当中的两个向量进行的加减法是一样的。
我们对比图4和图5,可以看出,sum(math%chinese) = 252 =6+15+126+99+6 , avg(math-chinese)=-1.6 = (6+15-4-31+6)/5=-8/5=1.6, min(math*chinese)=10864=min(13680,10864,16380,12870,13680), max(math/chinese)=1.1546=max(1.0526,1.1546,0.9692,0.7615,1.0526)。
因此我们就可以得出结论,sum(parameter),avg(parameter),min(parameter),max(parameter),是把parameter当做一个列向量,然后对这个列向量的每个数进行相应的运算。
因而,想做一个行方向的运算,只要让这个参数能够进行行方向的运算即可,而普通的四则运算,可以让每个列向量中的成员与另一个列向量对应位置的成员进行四则运算,由此可以实现行运算。
1.4 推而广之
既然可以先对两列进行“+”、“-”、“*”、“/”、“%”等五种运算,后进行sum,avg,min,max等四种运算,那么也可以对三列及三列以上进行“+”、“-”、“*”、“/”、“%”等五种运算,而后进行sum,avg,min,max等四种运算。
既然能够进行加减乘除取余这五种运算,那么求对数,正弦,余弦,正切,余切等普通科学计算器上有的运算,只要定义域合理,mysql都可以计算。注意,在正弦、余弦等三角函数运算的时候,传给sin,或者cos的参数是弧度制,意思是cos(
/2)=0,类似于这种的。
select sin(math) from mark;则对于math这一列的每一个成员,全都进行正弦运算。
对于对数,ln(x) = log(x),这是以自然对数e为底求x的对数的,对于log10(x)则是以10为底,求x的对数的。
select ln(math),log10(math) from mark;
图7. 对某一列进行对数运算
因此,我这里所谓的行方向的运算,就是指列向量之间对应成员之间的运算,这个运算可以像向量加减法那样直接写出来。
2 count函数
对于count函数来说,这个函数是对某些行(通过“where condition”来确定)进行计数。
比如计算,张三出现了几次,select name,count(*) from mark group by name;
图8. 计数
图9. 张三出现了多少次
3 统计学上运算
现在回到原来的问题,在行方向进行运算。比如你想计算一个班的所有人的总分,该怎么计算。
3.1 每行求和
我们知道对于一张表,如学生成绩单,一般的,除第一行以外的每一行都代表一个学生的相关信息,现在想把每个学生的成绩计算出来,并添加到原有的表,那该怎么办呢?
首先,给表添加一列,最好设为null。这样做的目的在于如果后面继续添加学生名单,你可以不用填写添加的这一列,以节省时间。
图10. 添加一列以及其结果
接着,给表更改数据
>update mark set zongfen=(math+chinese+english+lizong);
图11. 计算总分
在这里不能用sum(math+chinese+english+lizong)来计算,因为sum是针对列运算,最终的运算结果会是一个数。而我直接让列相加,是把每一列看出一个向量,用向量的加法来算出总分,而这个总分将是一个向量,向量的每个成员对应着每个学生。
3.2 加权总分
现在假设,高考改革了,数学比原来高到1.2倍,英语比原来低到0.8倍,语文和理综不变
>update mark set zongfen=(1.2*math+chinese+0.8*english+lizong);
图12. 加权总分
3.3 方差
总体方差的基本公式:(
(ai - a)^2 )/n
样本方差的基本公式:(
(ai - a)^2 )/(n-1)
mysql中总体标准差函数( population standard deviation):stddev_pop() ; 估计样本标准差:stddev_samp();
方差( population standard variance):var_pop(),样本方差(sample standard variance):var_samp();
我们现在想计算数学这门课的学生成绩的方差,以考量学生之间的差距:
图13. 方差
当我们通过avg(第i列列名)知道了均值,从上面那里知道了方差,根据以往经验,得出学生成绩的真实均值和标准差,我们就可以通过利用数理统计(或者概率论后面几章)中的各种参数估计,进行估计不知道的参数,通过估计区间,知道学生近段时间的学习状况是怎么样的,等等。
最后,大家可能会觉得,Excel和wps表格多么好用,为什么要用MySQL做这种统计学上的工作呢?也有人可能觉得用mysql workbench是多么的善解人意,为什么还要用全代码呢?我想呢,由于整个过程没有图形界面,做这些全靠记忆一些代码,通过这么折腾,这令我更加习惯于Linux系统,更加深入理解MySQL。从这些枯燥的代码当中找到乐趣。