Mysql 分组选择与group_concat
在其他的数据库中我们遇到分组选择的问题时,比如在分组中计算前10名的平均分
我们可以使用row_number()over() 比较方便的得到。
但是在mysql中,问题就被抛了出来,因为mysql并没有一个rownum内建数据元组访问方式。
在这里我提供三种方式来尝试解决
一.最基础的union的方式,放弃分组,采用union方式将多条查询的结果集放在一起做后续操作。 虽然我们可以在程序中预先获取所有分组,循环拼凑sql语句,但是这依然是很繁琐费时的,而且在目标需要分的组是海量的将会非常消耗系统资源。
二.使用采用子查询的方式,
例子
在上述语句中使用了一个子查询(select count(*))得到一个cnt数,这个数实际上是可以反映这条数据元组在他所在分组所排名名次的。
这种方式看似很美好,实际上子查询的效率出奇的烂,我实际跑起来,感觉mysql5.6对这样查询并没有多上优化,给每一条记录给出一个‘伪排名值’,天知道有多浪费资源。
三.使用group_concat()与substring_index配合解决
例子
Select substring_index(group_concat(report_period order by report_period desc),',',1) 。。。
通过一个额外的字段存放group_concat(),我们可以后续取出各个分组中对应排名的值,这可以算做一种化纵为橫。由于我们本来分组就要使用group by所以,group_concat()括号中的属性如果与外部的group by的属性一致并不会带来明显的开销增加。
不过由于返回的并不直接是我们需要的元组,而是一个排序属性值所以需要,在外嵌套一层查询
通常group_concat()作为一个优秀的辅助方法帮助我们保存分组操作中我们不在乎聚合统计值又无法忽略的字段,我们可以在多重场合下用到它。
本例中我们如果只是要一部分随机数据,不需要有序的数据(例如最大的前n条),我们可以采用在内层查询select中加入一个随机值,在外层查询中加入对随机值得排序结果来实现随机取数据。