在数据库表操作中,一个常见的需求是:如何按照创建时间,取出每天的第一条的记录。

然而,这并不是单纯依靠标准SQL语法就能完成的,而需要配合特定数据库实现的函数辅助才行。在MySQL中,这个函数即ROW_NUMBER()。

下面用一个临时创建的表,具体展示下用法:

text
 1$ mysql
 2
 3mysql> create table test0113 (grp int, value float);
 4Query OK, 0 rows affected (0.13 sec)
 5
 6mysql> insert into test0113 values (1, .1), (1, .2), (1, .3), (2, .2), (2, .4);
 7Query OK, 5 rows affected (0.02 sec)
 8Records: 5  Duplicates: 0  Warnings: 0
 9
10mysql> select * from test0113;
11+------+-------+
12| grp  | value |
13+------+-------+
14|    1 |   0.1 |
15|    1 |   0.2 |
16|    1 |   0.3 |
17|    2 |   0.2 |
18|    2 |   0.4 |
19+------+-------+
205 rows in set (0.00 sec)

ROW_NUMBER()需要配合OVER (PARTITION BY ... ORDER BY ...)的语法结构,来实现所需查询:

text
 1mysql> select grp, value, row_number() over (partition by grp order by value) row_num from test0113 order by grp, value;
 2+------+-------+---------+
 3| grp  | value | row_num |
 4+------+-------+---------+
 5|    1 |   0.1 |       1 |
 6|    1 |   0.2 |       2 |
 7|    1 |   0.3 |       3 |
 8|    2 |   0.2 |       1 |
 9|    2 |   0.4 |       2 |
10+------+-------+---------+
115 rows in set (0.00 sec)

有了这个结果后,再配合一层嵌套查询,就可以实现最开始的需求了:

text
1mysql> select * from (select grp, value, row_number() over (partition by grp order by value) row_num from test0113 order by grp, value) t1 where row_num = 1;
2+------+-------+---------+
3| grp  | value | row_num |
4+------+-------+---------+
5|    1 |   0.1 |       1 |
6|    2 |   0.2 |       1 |
7+------+-------+---------+
82 rows in set (0.00 sec)

参考: