mysql 重用技巧

一:分组排序

同事提了一个需求,要求按照某列分组,然后将各组的前几条抽取出来。

表结构

  1. CREATE TABLE `total_freq_ctrl`  
  2.   `time` int(10) unsigned NOT NULL,  
  3.   `machine` char(64) NOT NULL,  
  4.   `module` char(32) NOT NULL,  
  5.   `total_flow` int(10) unsigned NOT NULL,  
  6.   `deny_flow` int(10) unsigned NOT NULL,  
  7.   PRIMARY KEY (`module`,`machine`,`time`)  
  8. ENGINE=InnoDB DEFAULT CHARSET=utf8  

tudou@b2c.xiaomi.com

原sql

  1. SELECT machine, deny_flow, total_flow, time FROM total_freq_ctrl WHERE (SELECT COUNT(machine) FROM total_freq_ctrl WHERE machine A.machine AND time A.time) AND A.module 'all' ORDER BY A.time desc;  

只要将 1 改成N就变成取每组的前N条,因为我极其不喜欢子查询,就改就尝试改称join 的方式。

不过这里需要对所有数据进行排序才能确定每组的前N条,所以最佳优化也要全表扫描一次。

首先我要对表中数据进行排序,引入一个变量@row来做rownumber

  1. set @row=0;set @mid='';SELECT module, machine, time, @row:=@row+1 rownum FROM total_freq_ctrl order by module,machine,time desc limit 10;   
  2. Query OK, rows affected (0.00 sec)  
  3.   
  4. Query OK, rows affected (0.00 sec)  
  5.   
  6. +--------+---------------+------------+--------+  
  7. module machine       time       rownum  
  8. +--------+---------------+------------+--------+  
  9. all    10.201.20.181 1409640060       
  10. all    10.201.20.181 1409640000       
  11. all    10.201.20.181 1409639940       
  12. all    10.201.20.181 1409639880       
  13. all    10.201.20.97  1409640060       
  14. all    10.201.20.97  1409640000       
  15. all    10.201.20.97  1409639940       
  16. all    10.201.20.97  1409639880       
  17. all    10.201.20.98  1409640060       
  18. all    10.201.20.98  1409640000     10  
  19. +--------+---------------+------------+--------+  

rownumber已经出来了,再加一个@mid来进行分组
  1. set @row=0;set @mid='';SELECT module, machine, time,case when @mid machine then @row:=@row+1 else @row:=1 end rownum, @mid:=machine FROM total_freq_ctrl order by module,machine,time desc limit 20;  
  2. Query OK, rows affected (0.00 sec)  
  3.   
  4. Query OK, rows affected (0.00 sec)  
  5.   
  6. +--------+---------------+------------+--------+---------------+  
  7. module machine       time       rownum @mid:=machine  
  8. +--------+---------------+------------+--------+---------------+  
  9. all    10.201.20.181 1409640180      10.201.20.181  
  10. all    10.201.20.181 1409640120      10.201.20.181  
  11. all    10.201.20.181 1409640060      10.201.20.181  
  12. all    10.201.20.181 1409640000      10.201.20.181  
  13. all    10.201.20.181 1409639940      10.201.20.181  
  14. all    10.201.20.181 1409639880      10.201.20.181  
  15. all    10.201.20.97  1409640180      10.201.20.97   
  16. all    10.201.20.97  1409640120      10.201.20.97   
  17. all    10.201.20.97  1409640060      10.201.20.97   
  18. all    10.201.20.97  1409640000      10.201.20.97   
  19. all    10.201.20.97  1409639940      10.201.20.97   
  20. all    10.201.20.97  1409639880      10.201.20.97   
  21. all    10.201.20.98  1409640180      10.201.20.98   
  22. all    10.201.20.98  1409640120      10.201.20.98   
  23. all    10.201.20.98  1409640060      10.201.20.98   
  24. all    10.201.20.98  1409640000      10.201.20.98   
  25. all    10.201.20.98  1409639940      10.201.20.98   
  26. all    10.201.20.98  1409639880      10.201.20.98   
  27. +--------+---------------+------------+--------+---------------+  

好了,再外面加一层inner join 再对 rownumber 做限制 就可以拿到目标数据了。

tudou@b2c.xiaomi.com

  1. set @row=0;set @mid='';select a.*,b.rownum from total_freq_ctrl inner join (SELECT module, machine, time, case when @mid machine then @row:=@row+1 else @row:=1 end rownum, @mid:=machine mid FROM total_freq_ctrl order by module,machine,time desc) on b.module=a.module and b.machine=a.machine and b.time=a.time where b.rownum<5;  
  2. Query OK, rows affected (0.00 sec)  
  3.   
  4. Query OK, rows affected (0.00 sec)  
  5.   
  6. +------------+---------------+--------+------------+-----------+--------+  
  7. time       machine       module total_flow deny_flow rownum  
  8. +------------+---------------+--------+------------+-----------+--------+  
  9. 1409640360 10.201.20.181 all         53937      6058       
  10. 1409640300 10.201.20.181 all         52588      5701       
  11. 1409640240 10.201.20.181 all         54254      5608       
  12. 1409640180 10.201.20.181 all         54684      5811       
  13. 1409640360 10.201.20.97  all         50679      5307       
  14. 1409640300 10.201.20.97  all         50472      5239       
  15. 1409640240 10.201.20.97  all         51586      5509       
  16. 1409640180 10.201.20.97  all         50794      5378       
  17. 1409640360 10.201.20.98  all         84747      5652       
  18. 1409640300 10.201.20.98  all         84506      5696       
  19. 1409640240 10.201.20.98  all         84982      5513       
  20. 1409640180 10.201.20.98  all         83997      5623       
  21. +------------+---------------+--------+------------+-----------+--------+ 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值