程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 數據庫知識 >> MYSQL數據庫 >> MySQL綜合教程 >> MySQL分組排序取前N條記錄以及生成自動數字序列--groupby後limit外加rownumber

MySQL分組排序取前N條記錄以及生成自動數字序列--groupby後limit外加rownumber

編輯:MySQL綜合教程

MySQL分組排序取前N條記錄以及生成自動數字序列--groupby後limit外加rownumber


同事提了一個需求,要求按照某列分組,然後將各組的前幾條抽取出來。

表結構

CREATE TABLE `total_freq_ctrl` (
  `time` int(10) unsigned NOT NULL,
  `machine` char(64) NOT NULL,
  `module` char(32) NOT NULL,
  `total_flow` int(10) unsigned NOT NULL,
  `deny_flow` int(10) unsigned NOT NULL,
  PRIMARY KEY (`module`,`machine`,`time`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8
[email protected]

原sql

SELECT machine, deny_flow, total_flow, time FROM total_freq_ctrl A WHERE 1 > (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

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; 
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+---------------+------------+--------+
| module | machine       | time       | rownum |
+--------+---------------+------------+--------+
| all    | 10.201.20.181 | 1409640060 |      1 |
| all    | 10.201.20.181 | 1409640000 |      2 |
| all    | 10.201.20.181 | 1409639940 |      3 |
| all    | 10.201.20.181 | 1409639880 |      4 |
| all    | 10.201.20.97  | 1409640060 |      5 |
| all    | 10.201.20.97  | 1409640000 |      6 |
| all    | 10.201.20.97  | 1409639940 |      7 |
| all    | 10.201.20.97  | 1409639880 |      8 |
| all    | 10.201.20.98  | 1409640060 |      9 |
| all    | 10.201.20.98  | 1409640000 |     10 |
+--------+---------------+------------+--------+
rownumber已經出來了,再加一個@mid來進行分組
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;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+--------+---------------+------------+--------+---------------+
| module | machine       | time       | rownum | @mid:=machine |
+--------+---------------+------------+--------+---------------+
| all    | 10.201.20.181 | 1409640180 |      1 | 10.201.20.181 |
| all    | 10.201.20.181 | 1409640120 |      2 | 10.201.20.181 |
| all    | 10.201.20.181 | 1409640060 |      3 | 10.201.20.181 |
| all    | 10.201.20.181 | 1409640000 |      4 | 10.201.20.181 |
| all    | 10.201.20.181 | 1409639940 |      5 | 10.201.20.181 |
| all    | 10.201.20.181 | 1409639880 |      6 | 10.201.20.181 |
| all    | 10.201.20.97  | 1409640180 |      1 | 10.201.20.97  |
| all    | 10.201.20.97  | 1409640120 |      2 | 10.201.20.97  |
| all    | 10.201.20.97  | 1409640060 |      3 | 10.201.20.97  |
| all    | 10.201.20.97  | 1409640000 |      4 | 10.201.20.97  |
| all    | 10.201.20.97  | 1409639940 |      5 | 10.201.20.97  |
| all    | 10.201.20.97  | 1409639880 |      6 | 10.201.20.97  |
| all    | 10.201.20.98  | 1409640180 |      1 | 10.201.20.98  |
| all    | 10.201.20.98  | 1409640120 |      2 | 10.201.20.98  |
| all    | 10.201.20.98  | 1409640060 |      3 | 10.201.20.98  |
| all    | 10.201.20.98  | 1409640000 |      4 | 10.201.20.98  |
| all    | 10.201.20.98  | 1409639940 |      5 | 10.201.20.98  |
| all    | 10.201.20.98  | 1409639880 |      6 | 10.201.20.98  |
+--------+---------------+------------+--------+---------------+
好了,再外面加一層inner join 再對 rownumber 做限制 就可以拿到目標數據了。

[email protected]

set @row=0;set @mid='';select a.*,b.rownum from total_freq_ctrl a 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) b on b.module=a.module and b.machine=a.machine and b.time=a.time where b.rownum<5;
Query OK, 0 rows affected (0.00 sec)

Query OK, 0 rows affected (0.00 sec)

+------------+---------------+--------+------------+-----------+--------+
| time       | machine       | module | total_flow | deny_flow | rownum |
+------------+---------------+--------+------------+-----------+--------+
| 1409640360 | 10.201.20.181 | all    |      53937 |      6058 |      1 |
| 1409640300 | 10.201.20.181 | all    |      52588 |      5701 |      2 |
| 1409640240 | 10.201.20.181 | all    |      54254 |      5608 |      3 |
| 1409640180 | 10.201.20.181 | all    |      54684 |      5811 |      4 |
| 1409640360 | 10.201.20.97  | all    |      50679 |      5307 |      1 |
| 1409640300 | 10.201.20.97  | all    |      50472 |      5239 |      2 |
| 1409640240 | 10.201.20.97  | all    |      51586 |      5509 |      3 |
| 1409640180 | 10.201.20.97  | all    |      50794 |      5378 |      4 |
| 1409640360 | 10.201.20.98  | all    |      84747 |      5652 |      1 |
| 1409640300 | 10.201.20.98  | all    |      84506 |      5696 |      2 |
| 1409640240 | 10.201.20.98  | all    |      84982 |      5513 |      3 |
| 1409640180 | 10.201.20.98  | all    |      83997 |      5623 |      4 |
+------------+---------------+--------+------------+-----------+--------+

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved