MySQL偏移无限行


114

我想构造一个查询,在表中显示所有结果,但是从表的开头偏移5。据我所知,MySQL LIMIT需要一个限制和一个偏移量。有什么办法吗?


1
这是一个完全有效的问题,但是我想知道是否最好以编程方式获取所有内容并忽略前几条记录。考虑到似乎是最佳答案的恐惧(限制5,18444647007370955115),我非常希望解决MySQL LIMIT的限制。
cesoid 2015年

3
@cesoid如果需要的话limit 5000, 18446744073709551615。您不会仅仅为了让代码看起来漂亮就获取额外的5000行。
elipoultorak

@ user3576887我认为您是对的,我只是在考虑上面的问题,并假设5是唯一的要求,而不是一些可能更大的变化量(而不是解决其他人的问题)。
cesoid 2015年

我建议这是一项罕见的任务,可以接受解决方案的丑陋性。
里克·詹姆斯

Answers:


151

LIMITMySQL手册

要检索从某个偏移量到结果集结尾的所有行,可以为第二个参数使用较大的数字。该语句检索从第96行到最后一行的所有行:

SELECT * FROM tbl LIMIT 95, 18446744073709551615;

105
可怕!我来到这里的目的是希望MySQL使Limit子句成为可选的,但它还提供了偏移量...但是没有!我已经看到这18446744073709551615分散在整个代码中,我指责懒惰的程序员,但这是设计功能!
Petruza 2010年

8
糟糕的答案,但这就是MySQL Doc的官方说法。我能说@ _ @
GusDeCooL 2011年

21
18446744073709551615对于那些想知道的人来说是2 ^ 64-1。您可能要当心,因为您将无法以32位整数存储此值。您必须确保将其存储为字符串以确保兼容性。
AlicanC 2011年

13
可怕!他们需要比这更优雅... Limit -1或者Limit Null看起来很合理!或atleast Limit应该接受子查询,例如select * from table limit (select count(*) from table)
vulcan raven 2012年

19
使用php'PHP_INT_MAX'避免溢出效应。
卡尔·阿德勒

24

正如您提到的,LIMIT是必需的,因此您需要使用最大的限制,即18446744073709551615(未签名的BIGINT的最大值)

SELECT * FROM somewhere LIMIT 18446744073709551610 OFFSET 5

33
哇,这是MySQL小组的官方解决方案吗?
安东尼

12

如其他答案所述,MySQL建议使用18446744073709551615作为限制中的记录数,但请考虑以下几点:如果您获得了18,446,744,073,709,551,615条记录,该怎么办?实际上,如果您有1,000,000,000条记录,该怎么办?

也许您确实想要超过10亿条记录,但是我的意思是,您想要的数目有一定的限制,并且少于18百万个。为了稳定,优化和可能的可用性,我建议对查询设置一些有意义的限制。对于那些从未见过如此神奇的数字的人,这也将减少混乱,并具有至少一次传达您愿意处理多少条记录的额外好处。

如果您真的必须从数据库中获取所有18亿个记录,那么您真正想要的就是以1亿为增量获取它们并循环1840亿次。


您是对的,但将决定权交给开发人员并不是一个好选择
2017年

@amd您能解释一下吗?我不知道你想说什么。
塞西德

1
@cesoid我认为他是在说开发人员不应该是那些我同意的业务逻辑,而只能选择一个观点。假设您要向客户返回订单列表。绝对不会一次返回超过一百万,这是完全合理的,但限制为100可能会造成混乱。
秋季伦纳德

@amd我并不是说开发人员应该更改应用程序的行为,以避免使用18446744073709551615。我是说,他们应该考虑使用该数字作为客户端或接口设计人员的实现的一部分是否有意义的要求,并且几乎不可能是任何事情的正确实现。开发人员可能已经做出使用MySQL的决定,而没有询问是否会超过18百万个。
cesoid

5

另一种方法是选择一个自动增加的列,然后使用HAVING对其进行过滤。

SET @a := 0; 
select @a:=@a + 1 AS counter, table.* FROM table 
HAVING counter > 4

但是我可能会坚持使用上限方法。


谢谢,我想知道如何在PHP语句中放入这样的查询!我的意思是那样$sql = 'SET @a :=0 SELECT .....';
Reham Fahmy

2

正如其他人提到的,来自MySQL手册。为了实现这一点,可以使用无符号big int的最大值,即这个可怕的数字(18446744073709551615)。但是为了使它少一点混乱,您可以使用代字号“〜”按位运算符。

  LIMIT 95, ~0

它是按位取反的。结果“〜0”为18446744073709551615。


1
在MariaDB 10.3中不起作用:((我同时尝试了LIMIT 5, ~0LIMIT ~0 OFFSET 5。这是MySQL 8.0功能吗?
jurchiks

1
这在MySQL 5.7中不是问题-无效的语法。
Jonny Nott

0

就在今天,我正在阅读从mysql表中获取大量数据(超过一百万行)的最佳方法。一种方法是,按照建议,使用LIMIT x,y其中x的偏移和y你想要的最后一行返回。但是,正如我发现的那样,这并不是最有效的方法。如果您有自动递增的列,则可以轻松地使用SELECT带有WHERE子句的语句,该语句说明您要从哪个记录开始。

例如, SELECT * FROM table_name WHERE id > x;

似乎mysql在使用时会得到所有结果LIMIT,然后只显示适合偏移量的记录:不是最佳性能。

资料来源:这个问题的答案MySQL论坛。请注意,这个问题大约有6岁了。


13
如果您删除了一条记录,这将导致错误的结果。此方法特别危险,因为它在大多数时间都有效,而在不起作用时会默默地失败。
10

0

您可以使用带有LIMIT的MySQL语句:

START TRANSACTION;
SET @my_offset = 5;
SET @rows = (SELECT COUNT(*) FROM my_table);
PREPARE statement FROM 'SELECT * FROM my_table LIMIT ? OFFSET ?';
EXECUTE statement USING @rows, @my_offset;
COMMIT;

在MySQL 5.5.44中测试。因此,我们可以避免插入数字18446744073709551615。

注意:事务确保变量@rows与执行语句时考虑的表一致。


正如@amd所说:“在具有7M条记录的表上选择count(*)大约需要17秒”
Rodrirokr

-1

我知道这很旧,但是我没有看到类似的回复,所以这是我要使用的解决方案。

首先,我将在表上执行计数查询,以查看有多少条记录。该查询速度很快,通常执行时间可以忽略不计。就像是:

SELECT COUNT(*) FROM table_name;

然后,我将使用从计数获得的结果作为限制来构建查询(因为这是表可能返回的最大行数)。就像是:

SELECT * FROM table_name LIMIT count_result OFFSET desired_offset;

或者可能是这样的:

SELECT * FROM table_name LIMIT desired_offset, count_result;

当然,如有必要,您可以从count_result中减去期望的偏移量,以获得实际的准确值作为限制。如果我实际上可以确定要提供的适当限制,则传递“ 18446744073709551610”值就没有任何意义。


2
与7M记录的表SELECT COUNT(*)需要大约17S
AMD公司

-7
WHERE .... AND id > <YOUROFFSET>

id可以是您拥有的任何自动递增或唯一的数字列...


7
馊主意。如果您删除了一行,它将给出不正确的偏移量。
2014年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.