MySQL实现常用分析函数

分别在 MySQL5.7.25-log 和 8.0.16 环境中实现类似Oracle的分析函数(8.0版本中已支持,直接使用即可)。
一、创建测试数据
二、row_number() over()
三、rank() over()
四、dense_rank() over()
五、lag() over()
六、lead() over()
七、待补充

一、创建测试数据:
CREATE TABLE `devicecounter` (
  `roomid` int(11) DEFAULT NULL,
  `deviceid` int(11) DEFAULT NULL,
  `counter` decimal(12,4) DEFAULT NULL,
  `readtime` datetime DEFAULT NULL
) ENGINE=InnoDB;

INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (536, 147, 26.0000, '2020-01-17 10:21:16');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (536, 502, 872.2700, '2020-01-17 10:21:19');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3750, 4922, 1304.8000, '2020-01-17 10:21:30');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3750, 5164, 20.9450, '2020-01-17 10:21:36');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3928, 6282, 2514.7000, '2020-01-17 10:21:40');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3930, 6284, 2087.8300, '2020-01-17 10:42:11');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3930, 6284, 2087.7300, '2020-01-17 10:41:08');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3928, 6434, 70.0000, '2020-01-17 10:21:42');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3930, 6436, 18.5000, '2020-01-17 10:45:11');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3930, 6436, 18.0000, '2020-01-17 10:41:10');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3981, 7260, 5.6000, '2020-01-17 10:21:38');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7314, 6.6000, '2020-01-17 10:25:31');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7314, 5.8000, '2020-01-17 10:19:30');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3981, 7364, 838.7000, '2020-01-17 10:21:33');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7418, 253.5000, '2020-01-17 10:30:31');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7418, 252.7000, '2020-01-17 10:19:29');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (3981, 7468, 12.0000, '2020-01-17 10:21:29');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7522, 12.8000, '2020-01-17 10:29:31');
INSERT INTO `devicecounter`(`roomid`, `deviceid`, `counter`, `readtime`) VALUES (4038, 7522, 12.0000, '2020-01-17 10:19:30');
二、查询结果添加序列号,类Oracle 的row_number() OVER()

例1:不分组,全部数据添加序列号,类Oracle 的rownum伪列

#### 按照房间和设备排序,依次标注序列号
#########   MySQL5.7
mysql> SELECT
    ( @rownum := @rownum + 1 ) AS rownum,
    a.* 
FROM
    devicecounter a,
    ( SELECT @rownum := 0 ) AS t 
ORDER BY roomid,deviceid,counter; 
+--------+--------+----------+-----------+---------------------+
| rownum | roomid | deviceid | counter   | readtime            |
+--------+--------+----------+-----------+---------------------+
|      1 |    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |
|      2 |    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |
|      3 |   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |
|      4 |   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |
|      5 |   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |
|      6 |   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |
|      7 |   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |
|      8 |   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |
|      9 |   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |
|     10 |   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |
|     11 |   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |
|     12 |   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |
|     13 |   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |
|     14 |   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |
|     15 |   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |
|     16 |   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |
|     17 |   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |
|     18 |   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |
|     19 |   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |
+--------+--------+----------+-----------+---------------------+

#########   MySQL8.0 
mysql>SELECT
    ROW_NUMBER () OVER w AS 'row_number',
    a.* 
FROM devicecounter a 
WINDOW w AS ( ORDER BY roomid,deviceid,counter );

#或者下面写法:
SELECT
    ROW_NUMBER() OVER (ORDER BY roomid,deviceid,counter) AS 'row_number',
    a.* 
FROM devicecounter a;

查询结果同上,不予列出。

例2:先按roomid分组,再按照deviceid,counter排序,类Oracle 的row_number() OVER(PARTITION BY ORDER BY )

##### 先按照房间分组,再添加序列号
#########   MySQL5.7
mysql> SELECT
  a.*,
  IF( @room_id = roomid,@rownum := @rownum + 1, @rownum := 1 ) AS rownum,
    @room_id := roomid AS roomid1  
FROM
    devicecounter a,(SELECT @rownum := 0, @room_id := 0) AS t 
ORDER BY roomid,deviceid,counter;
+--------+----------+-----------+---------------------+--------+---------+
| roomid | deviceid | counter   | readtime            | rownum | roomid1 |
+--------+----------+-----------+---------------------+--------+---------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |      1 |     536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |      2 |     536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |      1 |    3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |      2 |    3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |      1 |    3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |      2 |    3928 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |      1 |    3930 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |      2 |    3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |      3 |    3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |      4 |    3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |      1 |    3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |      2 |    3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |      3 |    3981 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |      1 |    4038 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |      2 |    4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |      3 |    4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |      4 |    4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |      5 |    4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |      6 |    4038 |
+--------+----------+-----------+---------------------+--------+---------+

#########   MySQL8.0
mysql>SELECT
    a.*,
    ROW_NUMBER() OVER w AS 'row_number'
FROM devicecounter a 
WINDOW w AS ( PARTITION BY roomid order by deviceid,counter);

#或者下面写法:
SELECT
    a.*,
    ROW_NUMBER() OVER (PARTITION BY roomid order by deviceid,counter) AS 'row_number'
FROM devicecounter a;
三、rank,类似Oracle的 rank() over()

例1:不分组,全部数据按 roomid 排序,再添加序号,类Oracle 的rank() OVER(ORDER BY)

#########   MySQL5.7
mysql> SELECT
  a.*,
  @rownum := @rownum + 1  AS rownum,
  IF(@room_id = roomid, @rank := @rank,@rank := @rownum) AS rank,
  @room_id := roomid AS roomid1 
 FROM
    devicecounter a,(SELECT @rownum := 0, @rank := 0,@room_id:= 0) AS t 
ORDER BY roomid;
+--------+----------+-----------+---------------------+--------+------+---------+
| roomid | deviceid | counter   | readtime            | rownum | rank | roomid1 |
+--------+----------+-----------+---------------------+--------+------+---------+
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |      1 | 1    |     536 |
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |      2 | 1    |     536 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |      3 | 3    |    3750 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |      4 | 3    |    3750 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |      5 | 5    |    3928 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |      6 | 5    |    3928 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |      7 | 7    |    3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |      8 | 7    |    3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |      9 | 7    |    3930 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |     10 | 7    |    3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |     11 | 11   |    3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |     12 | 11   |    3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |     13 | 11   |    3981 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |     14 | 14   |    4038 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |     15 | 14   |    4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |     16 | 14   |    4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |     17 | 14   |    4038 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |     18 | 14   |    4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |     19 | 14   |    4038 |
+--------+----------+-----------+---------------------+--------+------+---------+

#########   MySQL8.0
mysql> SELECT
    a.*,
    rank() OVER w AS 'rank'
FROM devicecounter a
WINDOW w AS (order by roomid) ;

#或者下面写法:
SELECT
    a.*,
    rank() OVER (order by roomid) AS 'rank'
FROM devicecounter a ;

例2:先按roomid分组,再按deviceid排序,类Oracle 的rank() OVER(PARTITION BY ORDER BY)

#########   MySQL5.7
mysql> SELECT
  a.*,
  IF(@room_id = roomid, @rownum := @rownum + 1, @rownum := 1 ) AS rownum,
  IF(@device_id = deviceid, @rank := @rank,@rank := @rownum) AS rank ,
  @device_id := deviceid AS deviceid1,
  @room_id := roomid AS roomid1  
FROM
    devicecounter a,(SELECT @rownum := 0, @room_id := -1, @rank := 0,@device_id:= -1) AS t 
ORDER BY roomid,deviceid;
+--------+----------+-----------+---------------------+--------+------+-----------+---------+
| roomid | deviceid | counter   | readtime            | rownum | rank | deviceid1 | roomid1 |
+--------+----------+-----------+---------------------+--------+------+-----------+---------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |      1 | 1    |       147 |     536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |      2 | 2    |       502 |     536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |      1 | 1    |      4922 |    3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |      2 | 2    |      5164 |    3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |      1 | 1    |      6282 |    3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |      2 | 2    |      6434 |    3928 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |      1 | 1    |      6284 |    3930 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |      2 | 1    |      6284 |    3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |      3 | 3    |      6436 |    3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |      4 | 3    |      6436 |    3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |      1 | 1    |      7260 |    3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |      2 | 2    |      7364 |    3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |      3 | 3    |      7468 |    3981 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |      1 | 1    |      7314 |    4038 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |      2 | 1    |      7314 |    4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |      3 | 3    |      7418 |    4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |      4 | 3    |      7418 |    4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |      5 | 5    |      7522 |    4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |      6 | 5    |      7522 |    4038 |
+--------+----------+-----------+---------------------+--------+------+-----------+---------+

#########   MySQL8.0
mysql>SELECT
    a.*,
    rank() OVER w AS 'rank'
FROM devicecounter a 
WINDOW w AS (PARTITION BY roomid order by deviceid);

#或者下面写法:
mysql>SELECT
    a.*,
    rank() OVER (PARTITION BY roomid order by deviceidq) AS 'rank'
FROM devicecounter a ;
四、dense_rank,类Oracle 的 dense_rank() over()

例1:不分组,全部数据按roomid排序,再添加序号,类Oracle 的dense_rank() OVER(ORDER BY)

#########   MySQL5.7
mysql>  SELECT
  a.*,
    @rank := @rank + if(@room_id = roomid,0,1) AS rank ,
  @room_id := roomid AS roomid1  
FROM
    devicecounter a,(SELECT  @room_id := -1, @rank := 0,@device_id:= -1) AS t 
ORDER BY roomid,deviceid;
+--------+----------+-----------+---------------------+------+---------+
| roomid | deviceid | counter   | readtime            | rank | roomid1 |
+--------+----------+-----------+---------------------+------+---------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |    1 |     536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |    1 |     536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |    2 |    3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |    2 |    3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |    3 |    3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |    3 |    3928 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |    4 |    3930 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |    4 |    3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |    4 |    3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |    4 |    3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |    5 |    3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |    5 |    3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |    5 |    3981 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |    6 |    4038 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |    6 |    4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |    6 |    4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |    6 |    4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |    6 |    4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |    6 |    4038 |
+--------+----------+-----------+---------------------+------+---------+
#########   MySQL8.0
mysql>mysql>SELECT
    a.*,
    dense_rank() OVER w AS 'dense_rank'
FROM devicecounter a 
WINDOW w AS (order by roomid);

#或者下面写法:
mysql>SELECT
    a.*,
    dense_rank() OVER (order by roomid) AS 'dense_rank'
FROM devicecounter a ;

例2:先按roomid分组,再按deviceid排序,类Oracle 的dense_rank() OVER(PARTITION BY ORDER BY)

#########   MySQL5.7
mysql> SELECT
  a.*,
    IF(@room_id = roomid, @rank := @rank + if(@device_id = deviceid,0,1),@rank := 1) AS dense_rank ,
    @device_id := deviceid AS deviceid1,
  @room_id := roomid AS roomid1  
FROM
    devicecounter a,(SELECT  @room_id := -1, @rank := 0,@device_id:= -1) AS t 
ORDER BY roomid,deviceid;
+--------+----------+-----------+---------------------+------------+-----------+---------+
| roomid | deviceid | counter   | readtime            | dense_rank | deviceid1 | roomid1 |
+--------+----------+-----------+---------------------+------------+-----------+---------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |          1 |       147 |     536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |          2 |       502 |     536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |          1 |      4922 |    3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |          2 |      5164 |    3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |          1 |      6282 |    3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |          2 |      6434 |    3928 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |          1 |      6284 |    3930 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |          1 |      6284 |    3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |          2 |      6436 |    3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |          2 |      6436 |    3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |          1 |      7260 |    3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |          2 |      7364 |    3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |          3 |      7468 |    3981 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |          1 |      7314 |    4038 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |          1 |      7314 |    4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |          2 |      7418 |    4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |          2 |      7418 |    4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |          3 |      7522 |    4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |          3 |      7522 |    4038 |
+--------+----------+-----------+---------------------+------------+-----------+---------+

#########   MySQL8.0
mysql>SELECT
    a.*,
    dense_rank() OVER w AS 'dense_rank'
FROM devicecounter a 
WINDOW w AS (PARTITION BY roomid order by deviceid);

#或者下面写法:
mysql> SELECT
    a.*,
    dense_rank() OVER (PARTITION BY roomid order by deviceid) AS 'dense_rank'
FROM devicecounter a ;
五、lag,类Oracle 的 lag() over()

例1:不分组,全部数据按roomid,deviceid升序排序,类Oracle 的lag() OVER(ORDER BY)

#########   MySQL5.7
mysql> SELECT
  a.*,
    @lag  as lag_field,
    @lag:=deviceid  
FROM
    devicecounter a,(SELECT  @lag := '') AS t 
ORDER BY roomid,deviceid;
+--------+----------+-----------+---------------------+-----------+----------------+
| roomid | deviceid | counter   | readtime            | lag_field | @lag:=deviceid |
+--------+----------+-----------+---------------------+-----------+----------------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |           |            147 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |       147 |            502 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |       502 |           4922 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |      4922 |           5164 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |      5164 |           6282 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |      6282 |           6434 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |      6434 |           6284 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 |      6284 |           6284 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |      6284 |           6436 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 |      6436 |           6436 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |      6436 |           7260 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 |      7260 |           7364 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |      7364 |           7468 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |      7468 |           7314 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 |      7314 |           7314 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 |      7314 |           7418 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 |      7418 |           7418 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |      7418 |           7522 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 |      7522 |           7522 |
+--------+----------+-----------+---------------------+-----------+----------------+

#########   MySQL8.0
mysql> SELECT
  a.*,
    lag(deviceid) over w as lag_field
FROM
    devicecounter a  
WINDOW w AS (ORDER BY roomid,deviceid);

#或者下面写法:
mysql> SELECT
  a.*,
    lag(deviceid) over(ORDER BY roomid,deviceid) as lag_field
FROM
    devicecounter a ;

例2:先按roomid分组,再按roomid,deviceid排序,类Oracle 的lag() OVER(PARTITION BY ORDER BY)

#########   MySQL5.7
mysql> SELECT
  a.*,
    if(@room_id=roomid,@lag,'') as lag_field,
    @lag:=deviceid,
    @room_id:=roomid
FROM
    devicecounter a,(SELECT  @lag := '',@room_id:=-1) AS t 
ORDER BY roomid,deviceid;
+--------+----------+-----------+---------------------+-----------+----------------+------------------+
| roomid | deviceid | counter   | readtime            | lag_field | @lag:=deviceid | @room_id:=roomid |
+--------+----------+-----------+---------------------+-----------+----------------+------------------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 |           |            147 |              536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 | 147       |            502 |              536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 |           |           4922 |             3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 | 4922      |           5164 |             3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 |           |           6282 |             3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 | 6282      |           6434 |             3928 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 |           |           6284 |             3930 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 | 6284      |           6284 |             3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 | 6284      |           6436 |             3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 | 6436      |           6436 |             3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 |           |           7260 |             3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 | 7260      |           7364 |             3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 | 7364      |           7468 |             3981 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 |           |           7314 |             4038 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 | 7314      |           7314 |             4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 | 7314      |           7418 |             4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 | 7418      |           7418 |             4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 | 7418      |           7522 |             4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 | 7522      |           7522 |             4038 |
+--------+----------+-----------+---------------------+-----------+----------------+------------------+

#########   MySQL8.0
mysql> SELECT
  a.*,
    lag(deviceid) over w as lag_field
FROM
    devicecounter a  
WINDOW w AS (PARTITION by roomid ORDER BY roomid,deviceid);

#或者下面写法:
mysql> SELECT
  a.*,
    lag(deviceid) over(PARTITION by roomid ORDER BY roomid,deviceid) as lag_field
FROM
    devicecounter a ;
六、lead,类Oracle 的 lead() over()

例1:不分组,全部数据按roomid,deviceid,counter升序排序,类Oracle 的lead() OVER(ORDER BY)

#########   MySQL5.7   先全部降序,获取前一个值,然后再升序即可
mysql> select * from (
SELECT
  a.*,
    @lead  as lead_field,
    @lead:=deviceid  
FROM
    devicecounter a,(SELECT  @lead := '') AS t 
ORDER BY roomid desc ,deviceid desc,counter desc)tt 
ORDER BY roomid ,deviceid,counter;
+--------+----------+-----------+---------------------+------------+-----------------+
| roomid | deviceid | counter   | readtime            | lead_field | @lead:=deviceid |
+--------+----------+-----------+---------------------+------------+-----------------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 | 502        |             147 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 | 4922       |             502 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 | 5164       |            4922 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 | 6282       |            5164 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 | 6434       |            6282 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 | 6284       |            6434 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 | 6284       |            6284 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 | 6436       |            6284 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 | 6436       |            6436 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 | 7260       |            6436 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 | 7364       |            7260 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 | 7468       |            7364 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 | 7314       |            7468 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 | 7314       |            7314 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 | 7418       |            7314 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 | 7418       |            7418 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 | 7522       |            7418 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 | 7522       |            7522 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |            |            7522 |
+--------+----------+-----------+---------------------+------------+-----------------+

#########   MySQL8.0
mysql> SELECT
  a.*,
    lead(deviceid) over w as lead_field
FROM
    devicecounter a  
WINDOW w AS (ORDER BY roomid,deviceid,counter);

#或者下面写法:
mysql> SELECT
  a.*,
    lead(deviceid) over( ORDER BY roomid,deviceid,counter) as lead_field
FROM
    devicecounter a ;

例2:先按roomid分组,再按deviceid,counter排序,类Oracle 的lead() OVER(PARTITION BY ORDER BY)

#########   MySQL5.7
mysql> select * from ( SELECT
  a.*,
    if(@room_id=roomid,@lag,'') as lead_field,
    @lead:=deviceid,
    @room_id:=roomid
FROM
    devicecounter a,(SELECT  @lead := '',@room_id:=-1) AS t 
ORDER BY roomid desc ,deviceid desc,counter desc )tt 
ORDER BY roomid ,deviceid,counter;
+--------+----------+-----------+---------------------+------------+----------------+------------------+
| roomid | deviceid | counter   | readtime            | lead_field | @lag:=deviceid | @room_id:=roomid |
+--------+----------+-----------+---------------------+------------+----------------+------------------+
|    536 |      147 | 26.0000   | 2020-01-17 10:21:16 | 502        |            147 |              536 |
|    536 |      502 | 872.2700  | 2020-01-17 10:21:19 |            |            502 |              536 |
|   3750 |     4922 | 1304.8000 | 2020-01-17 10:21:30 | 5164       |           4922 |             3750 |
|   3750 |     5164 | 20.9450   | 2020-01-17 10:21:36 |            |           5164 |             3750 |
|   3928 |     6282 | 2514.7000 | 2020-01-17 10:21:40 | 6434       |           6282 |             3928 |
|   3928 |     6434 | 70.0000   | 2020-01-17 10:21:42 |            |           6434 |             3928 |
|   3930 |     6284 | 2087.7300 | 2020-01-17 10:41:08 | 6284       |           6284 |             3930 |
|   3930 |     6284 | 2087.8300 | 2020-01-17 10:42:11 | 6436       |           6284 |             3930 |
|   3930 |     6436 | 18.0000   | 2020-01-17 10:41:10 | 6436       |           6436 |             3930 |
|   3930 |     6436 | 18.5000   | 2020-01-17 10:45:11 |            |           6436 |             3930 |
|   3981 |     7260 | 5.6000    | 2020-01-17 10:21:38 | 7364       |           7260 |             3981 |
|   3981 |     7364 | 838.7000  | 2020-01-17 10:21:33 | 7468       |           7364 |             3981 |
|   3981 |     7468 | 12.0000   | 2020-01-17 10:21:29 |            |           7468 |             3981 |
|   4038 |     7314 | 5.8000    | 2020-01-17 10:19:30 | 7314       |           7314 |             4038 |
|   4038 |     7314 | 6.6000    | 2020-01-17 10:25:31 | 7418       |           7314 |             4038 |
|   4038 |     7418 | 252.7000  | 2020-01-17 10:19:29 | 7418       |           7418 |             4038 |
|   4038 |     7418 | 253.5000  | 2020-01-17 10:30:31 | 7522       |           7418 |             4038 |
|   4038 |     7522 | 12.0000   | 2020-01-17 10:19:30 | 7522       |           7522 |             4038 |
|   4038 |     7522 | 12.8000   | 2020-01-17 10:29:31 |            |           7522 |             4038 |
+--------+----------+-----------+---------------------+------------+----------------+------------------+

#########   MySQL8.0
mysql> SELECT
  a.*,
    lead(deviceid) over w as lead_field
FROM
    devicecounter a  
WINDOW w AS (partition by roomid ORDER BY deviceid,counter);

#或者下面写法:
mysql>SELECT
  a.*,
    lead(deviceid) over(partition by roomid ORDER BY deviceid,counter) as lead_field
FROM
    devicecounter a ;

你可能感兴趣的:(MySQL实现常用分析函数)