最近有个任务是关于cms文章发布统计,统计分为两步,第一步是统计所有会员发布的文章总数,并按照发布文章总量倒序排列。同时点击每个会员显示每个会员在每个栏目上发布的文章个数。
形如这样的:
用户名 |
投稿数量 |
排名 |
操作 |
小明 |
10 |
1 |
栏目投稿数据 |
小红 |
5 |
2 |
栏目投稿数据 |
小强 |
1 |
3 |
栏目投稿数据 |
点击“栏目投稿数据“进入用户发布的文章在每个栏目对应的数据。如下:(小明)
栏目名称 |
投稿数量 |
新闻 |
20 |
----正式新闻 |
12 |
----娱乐新闻 |
3 |
视频 |
6 |
----政事视频 |
3 |
----小视频 |
2 |
数据库构架为:
1、 cms_model:功能为后台自定义添加数据库,每添加一个cms_model表记录就会新增一个对应的数据表,表名自定义。
字段:
id,name,desc,tablename,type
type(0普通,3表单模型0:栏目,1:单网页,2:外链)
2、 cms_category:存放栏目的数据表。
字段:
Id,type,m_id,p_id,name,order
type(0:栏目,1:单网页,2:外链)
3、 剩下的表都是自定义的,不会知道名字的。只知道初始化字段:
Id,title,inputtime,username
4、member:
id,name
基于以上情况,进行数据统计。
因为存放投稿数据的表不确定,所以采取链表的方式应该没办法了,于是我才用了procedure。
Sql如下:
1 create procedure(in starttime int,in endtime int) 2 3 begin 4 5 DECLARE done int default false; 6 7 DECLARE table_name varchar(20); 8 9 DECLARE curl CURSOR FOR select tablename from cms_model where type=0; 10 11 DECLARE CONTINUE HANDLER FOR not found set done=true; 12 13 14 15 drop table if exists `cms_table_mem`; 16 17 set @sqlstr = concat(“ 18 19 create table cms_table_mem( 20 21 id int unsigned not null primary key auto_increment, 22 23 count int unsigned not null default 0, 24 25 username varchar(20) not null 26 27 )engine=memory default charset=utf8;” 28 29 ); 30 31 prepare sqlstr from @sqlstr; 32 33 execute sqlstr; 34 35 deallocate prepare sqlstr; 36 37 38 39 open curl; 40 41 read_loop:LOOP 42 43 fetch curl into table_name; 44 45 if done then 46 47 leave read_loop; 48 49 end if; 50 51 if table_name !=’’ then 52 53 set @tab = table_name; 54 55 set @s=concat(“insert into cms_table (count,username) select count(*) as count,username from ”,@tab,” where username != ‘’ and inputtime >”,starttime,” and inputtime <=”,endtime,” group by username”); 56 57 prepare sq from @s; 58 59 execute sq; 60 61 deallocate prepare sq; 62 63 else 64 65 iterate read_loop; 66 67 end if; 68 69 end loop; 70 71 close curl; 72 73 end;
以上这么做,是为了将统计结果统一放在一个数据表中,引擎采取memory,主要是为了快速。
接下来就是链表统计了
1 select sm.id,sm.`name` ,sum(m.count) as count from member as sm left join cms_table_mem as m on sm.name = m.username group by sm.name order by count desc limit 0,10
分页问题大家都懂,就不具体了。
这样就能统计出用户在不同栏目投稿的数量了。
接下来就是对指定的会员在不同栏目投稿的分布统计了。
首先对栏目进行树形归类,
代码如下:
1 SELECT c.id,c.name,c.p_id,c.m_id,m.tablename FROM cms_category AS c LEFT JOIN cms_model AS m ON c.m_id=m.id WHERE and c.type = 0 ORDER BY c.p_id ASC, c.order ASC
执行结果:$catlist
function tree($catLists,$p_id = 0,$deepth = 1) { static $arr = array(); foreach($catLists as $k => $v){ if($v['p_id'] == $p_id){ $v['deepth'] = $deepth; $arr[] = $v; unset($catLists[$k]); tree($catLists,$v['id'],$deepth+1); } } return $arr; }
$catLists = tree($catlist);
获得这个树形数组后,将子栏目的总量叠加到父栏目上
1 function sum($catLists,$params) 2 { 3 $level_array = array_unique(array_column($catLists,'deepth')); 4 5 $max_level = end($level_array); 6 7 $catsum = array(); 8 9 foreach($catLists as $k => $v){ 10 $where = "catid = ".$v['id']." and stat = 1 and inputtime >= ".$params['start']." and inputtime < ".$params['end'].""; 11 12 if(!empty($params['username'])){ 13 $where .= " and username = '".$params['username']."'"; 14 }
//这里是框架问题,不同的框架不同的统计方式。 15 $num = Model($v['tablename'])->count('*', $where); 16 $v['count'] = (int)$num; 17 $catsum[$v['id']] = $v; 18 } 19 20 $cur_pid = 0; 21 22 for($cur_level = $max_level;$cur_level > 1;$cur_level--){ 23 foreach($catsum as $v){ 24 if($v['deepth'] != $cur_level){ 25 continue; 26 } 27 28 if($cur_pid == 0){ 29 $cur_pid = $v['p_id']; 30 $catsum[$cur_pid]['count'] += $v['count']; 31 }else{ 32 if($v['p_id'] == $cur_pid){ 34 $catsum[$cur_pid]['count'] += $v['count']; 36 }else{ 38 $cur_pid = $v['p_id']; 40 $catsum[$cur_pid]['count'] += $v['count']; 42 } 43 } 44 } 45 } 46 47 $all = 0; 48 foreach($catsum as $v){ 49 if($v['deepth'] == 1){ 50 $all += $v['count']; 51 } 52 } 53 54 return array('tree'=>$catsum,'all'=>$all); 55 }
$sum =sum($catLists,array('start'=>$start,'end'=>$end));
这段代码的意思是先对每个栏目都进行文章统计,但是因为父栏目的文章数量应该是自己的数量加上子栏目的数量总和。所以还得进行二次叠加。
因为已经把栏目按照父子关系排列好了,所以问题就简单了,我是按照deepth值进行递加的,就是从最底层开始递加,将结果递加到上一级,循环执行,知道上一级的deepth为1。
这样结果就出来了。
因为篇幅和时间原因,可能写的不太清楚,也可能不是最优化。最优化的算法还在探索中。顺便原谅我的排版吧。