每隔N行生成一个汇总行(总结)

接前文
http://blog.itpub.net/29254281/viewspace-2149120/
http://blog.itpub.net/29254281/viewspace-2149309/

处理这种每隔N行生成一个汇总行的需求,一共有三种方式


  1. drop table t;
  2. create table t (c int);
  3. insert into t values
  4. (15),(7),(9),(10),(7),(8),(20),(16),(9),(19),
  5. (14),(10),(11),(10),(10),(12),(7),(10),(7),(9);
  6. commit;


  7. select * from t;
每隔N行生成一个汇总行(总结)_第1张图片

为了简单,就按照这个自然顺序 ,每三行生成一个汇总行,sum前三行的值。

第一招,效率低下容易理解
  1. select case when c is null then '汇总' else '' end s,ifnull(c,sumc) c from (  
  2.     select ceil(id/3) l,c,null sumc  
  3.     from   
  4.     (  
  5.         select @id:=@id+1 id, t1.* from t t1,(select @id:=0) vars    
  6.     ) t2  
  7.     union all    
  8.     select ceil(id/3) l,null,sum(c)   
  9.     from   
  10.     (  
  11.         select @id1:=@id1+1 id, t1.* from t t1,(select @id1:=0) vars    
  12.     ) t3  
  13.     group by l  
  14. ) t order by l,ifnull(c,'9999'); 

结果:
每隔N行生成一个汇总行(总结)_第2张图片

第二招,数字辅助表补全. 性能较好. 计算汇总行,理解稍微复杂.

先增加一个数字辅助表 nums
  1. create table nums(id int not null primary key);

  2. delimiter $$
  3. create procedure pCreateNums(cnt int)
  4. begin
  5.     declare s int default 1;
  6.     truncate table nums;
  7.     while s<=cnt do
  8.         insert into nums select s;
  9.         set s=s+1;
  10.     end while;
  11. end $$
  12. delimiter ;

  13. delimiter $$
  14. create procedure pFastCreateNums(cnt int)
  15. begin
  16.     declare s int default 1;
  17.     truncate table nums;
  18.     insert into nums select s;
  19.     while s*2<=cnt do
  20.         insert into nums select id+from nums;
  21.         set s=s*2;
  22.     end while;
  23. end $$
  24. delimiter ;

初始化数字辅助表
call pFastCreateNums(100000);

然后

  1. select s,ifnull(c,cc) c  
  2. from (    
  3.     select     
  4.     case when rn is null then '汇总' else '' end s,     
  5.     t4.c,  
  6.     if(mod(t3.id,4)!=0 ,case when @total=-1 then @total:=t4.c else @total:=@total+t4.c end,@total) cc,  
  7.     case when mod(t3.id,4)=0 then @total:=-1 else null end     
  8.     from (    
  9.         select * from nums where id<=    
  10.         (select (ceil(count(*)/4)+1)*5  from t )    
  11.     ) t3    
  12.     left join (    
  13.         select     
  14.         case when mod(@rn+1,4)=0 then @rn:=@rn+2 else @rn:=@rn+1 end rn ,    
  15.         t1.* from t t1,(select @rn:=0,@total:=0) vars      
  16.     ) t4 on(t3.id=t4.rn)    
  17. ) result;    

这个理解稍微有点复杂,
第二招改进版本
  1. select s,ifnull(c,cc) c    
  2. from (      
  3.     select       
  4.     case when rn is null then '汇总' else '' end s,       
  5.     t4.c,    
  6.     case when t4.c is not null then @total:=@total+t4.c when t4.c is null then @total+(@total:=0) end cc       
  7.     from (      
  8.         select * from nums where id<=      
  9.         (select (ceil(count(*)/4)+1)*5  from t )      
  10.     ) t3      
  11.     left join (      
  12.         select       
  13.         case when mod(@rn+1,4)=0 then @rn:=@rn+2 else @rn:=@rn+1 end rn ,      
  14.         t1.* from t t1,(select @rn:=0,@total:=0) vars        
  15.     ) t4 on(t3.id=t4.rn)      
  16. ) result where ifnull(c,cc) is not null;  

好理解多了,只是有冗余行数。
每隔N行生成一个汇总行(总结)_第3张图片


第三招,又是王工的大招. 性能比第二招快15%-20%。可读性强 好理解。整体还简短。
  1. select case when id is null then '汇总' else '' end s,sum(c) c from (  
  2.     select @id:=@id+1 id, t1.* from t t1,(select @id:=0) vars      
  3. ) t2  
  4. group by ceil(t2.id/3),t2.id with rollup;  


来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/29254281/viewspace-2149337/,如需转载,请注明出处,否则将追究法律责任。

转载于:http://blog.itpub.net/29254281/viewspace-2149337/

你可能感兴趣的:(每隔N行生成一个汇总行(总结))