在MySQL中选择最后一行

247

如何在MySQL表中选择最后一行?

我正在插入数据,需要检索前一行的列值。

该表中有一个自动递增。


8
“最后一行”是指具有最高ID的行还是最近添加的行? - EboMike
1
最后一行是什么 - 表中是否有auto_increment或DATETIME列? - OMG Ponies
是的,其中有一个auto_increment。我想要最近添加的一个。 - esqew
10
正如EboMike和OMG Ponies所说,一个集合中不存在最后一行。如果我给你一个装满球的袋子并让你给我拿出最后一个球,你会怎么做? - Vincent Savard
“装满球的袋子”比喻的问题在于,你可以使用“SELECT * FROM tablename LIMIT 1”语句,它会给你集合中的第一行。如果袋子里有第一个球,那么也应该有最后一个球。 - SkippyFlipjack
11个回答

506

是的,在那里有一个auto_increment

如果您想要表中所有行中的最后一行,则现在使用MAX(id)是正确答案! 有点像:

SELECT fields FROM table ORDER BY id DESC LIMIT 1;

22
如果需要对数百万行进行排序,我担心这会变得很慢,不是吗? - Slawa
5
我刚刚在2000万行数据上运行了这个查询,速度非常快。我猜想可能有一些特殊情况来处理这个查询。(编辑:MySQL 5.7版本,使用InnoDB引擎) - Daniel Buckmaster
1
@Pekka:我不想使用order by,还有其他的选项吗? - shiva
10
如果 id 被索引了,那么就不会出现这种情况。 - user207421

37

请记住,关系型数据库中的表只是行的集合。而在数学中,集合是无序的集合。没有第一行或最后一行;没有上一行或下一行。

您需要先按某个字段对无序行集进行排序,然后可以按照您定义的顺序自由迭代结果集。

由于您有一个自动递增字段,我假设您希望它成为排序字段。在这种情况下,您可能需要执行以下操作:

SELECT    *
FROM      your_table
ORDER BY  your_auto_increment_field DESC
LIMIT     1;

我们首先按照 your_auto_increment_field(或你所命名的字段)以降序排列无序行集。然后,我们使用 LIMIT 1 限制结果集只返回第一行。


36

你可以将@spacepille建议的两个查询组合成一个查询,如下所示:

SELECT * FROM `table_name` WHERE id=(SELECT MAX(id) FROM `table_name`);

它应该运行得非常快,但对于INNODB表格,它比ORDER+LIMIT慢了几毫秒。


1
@karthikeyan 四天前写了他的答案,而我在2015年12月回答了这个问题。 - vzr
不,我在4天前编辑并纠正了一些拼写...发帖日期是2014年,已经过去将近1年6个月了:) - Dwza
2
只是为了澄清,vzr是正确的。'Jun 14'表示2016年6月14日,此时@karthikeyan仅成为会员两个月。 - Robert Brisita
1
所以... @karthikeyan 的答案是这个的复制! - Cliff Burton

26

在有许多行的表上,很可能有两个查询速度更快...

SELECT @last_id := MAX(id) FROM table;

SELECT * FROM table WHERE id = @last_id;

11

几乎每个数据库表中都有一个自增列(通常是id)。

如果您想要该表中所有行中的最后一行,

SELECT columns FROM table ORDER BY id DESC LIMIT 1;

或者

您可以将两个查询组合成一个查询,它看起来像这样:

SELECT columns FROM table WHERE id=(SELECT MAX(id) FROM table);

1
自动递增仅在数据库管理员(或创建表的人)实现了自动递增时才存在。 - WhatsThePoint

8

这里有许多答案都在说同样的事情(按照自动增量列排序),这是可以的,前提是你有一个被索引的自动递增列。

另外需要注意的是,如果你有这样一个字段并且它是主键,那么使用“order by”和“select max(id)”不会对性能造成任何损失。主键是数据库文件中数据的排序方式(至少对于InnoDB来说),关系型数据库系统知道数据的结束位置,并且可以将“order by id + limit 1”优化为达到“max(id)”。

现在少有人走的路是没有自动递增的主键。也许主键是由3个字段组成的自然键...

但并非完全没有办法。从编程语言中,你可以首先获取行数:

SELECT Count(*) - 1 AS rowcount FROM <yourTable>;

然后在 LIMIT 子句中使用获取的数字。

SELECT * FROM orderbook2
LIMIT <number_from_rowcount>, 1

不幸的是,MySQL不允许在LIMIT子句中使用子查询或用户变量。


你也可以使用以下语句: SELECT * FROM orderbook2 LIMIT 1 OFFSET <number_from_rowcount - 1> - Marcellinus

8

4
好的。大多数良好的MySQL接口库都有专门的方法来处理这个问题,然而这个问题并没有标记为PHP,而是通用的MySQL语法。 - vzr

6

如果您想获取最近添加的记录,可以添加时间戳并按照最高时间戳的相反顺序选择排序,并限制为1条。如果您想按ID排序,则按ID排序。如果您想使用刚刚添加的记录,请使用mysql_insert_id


3
您可以在LIMIT命令中使用OFFSET
SELECT * FROM aTable LIMIT 1 OFFSET 99

如果你的表格有100行,这段代码将返回最后一行,而不必依赖主键。


1

在一次查询中没有ID:

SELECT * FROM table_name LIMIT 1 OFFSET (SELECT COUNT(*) - 1 FROM table_name)

您的SQL语法存在错误,请检查与您的MySQL服务器版本相对应的手册,以获取在第1行附近使用的正确语法,该语法为'(SELECT COUNT(*) - 1 FROM table_name)'。 - Muhammad Sulaiman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接