我有一个专栏
id
-----
1
32
3
6
5
22
54
21
问题1:如何从列中选择除前3条记录之外的所有记录?
问题2:如何选择最后3条记录?
-谢谢。
由于LIMIT的一些限制,您基本上需要将此类查询放入存储过程中。您不能在纯 sql 中使用子选择或变量。在存储过程中,您可以使用变量。
这行得通,不幸的是我无法在sqlfiddle中显示它,因为它们似乎对存储过程的支持有限。
drop procedure if exists all_but_3;
delimiter //
create procedure all_but_3()
begin
declare v_max bigint unsigned default ~0;
select * from your_table limit 3, v_max;
end//
delimiter ;
drop procedure if exists last_3;
delimiter //
create procedure last_3()
begin
declare v_max bigint;
declare v_mid bigint;
select count(*) from your_table into v_max;
set v_mid := v_max - 3;
select * from your_table limit v_mid, v_max;
end//
delimiter ;
call all_but_3();
call last_3();
在与@fthiella 讨论了其他答案之一后,我决定详细说明它是如何工作的。
使用 InnoDB 作为引擎的表将始终具有聚集索引。总是。这是他们将数据存储在 InnoDB 中的方式,并且在任何情况下都无法创建没有聚集索引的表。
如果有一个或第一个唯一索引且所有列都设置为非空,InnoDB 将选择主键。如果不存在这样的索引,InnoDB 将创建一个带有行 id 的隐藏列。此行 ID 的工作方式类似于自动增量,如果它有助于将其视为具有自动增量的不可见列,我认为这很好。
InnoDB 将进一步根据使用的索引返回行。它将始终使用一些索引(检索数据的唯一方法是使用二级索引、聚集索引或组合),因此在没有显式创建的索引的情况下,隐藏聚集索引会返回行。
这意味着针对没有主键和唯一索引且所有列都设置为非空且没有 ORDER BY 的表的查询将按照插入的顺序返回行。
这就是这个问题的情况,也是我和许多其他答案的基础。
我并不是说这是处理数据的好方法。在使用此解决方案之前,您应该考虑以下几点:
所有这些都记录在案,对于 5.5,这是此页面上的第三个要点
选择除前 3 条记录之外的所有记录:
从 table1 限制 3 中选择 id,18446744073709551615;
选择最后 3 条记录:
select a.id from (select @row_num:=@row_num+1 as RowNumber,id from table1, (select @row_num:=0) x order by RowNumber desc) 作为限制 3;
使用限制
对于#1,您理论上需要知道行数,但您可以只输入一个巨大的数字:
SELECT bleh FROM blah LIMIT 3, 18446744073709551615
(18446744073709551615 是可能的最大数量——感谢亚历克斯瓦西向我指出这一点)
对于#2,您确实需要知道记录数:
SELECT bleh FROM blah LIMIT NUM-3, 3
您必须从单独的查询中获取行数(这应该是 NUM 所在的位置)。
如果有可以排序的条件,则实际上可以在不进行完整计数的情况下执行第二个查询:
SELECT bleh FROM blah ORDER BY field DESC LIMIT 3
我假设情况并非如此。
(如果您不想对表进行计数,另一种选择是只提取所有数据并忽略代码域 [PHP、C 等] 中的前 3 行或最后 3 行。)
试试这个:
totalCounts = SELECT COUNT(*) FROM tbl;
SELECT * FROM tbl LIMIT 3,totalCounts
# Retrieve rows 4 to number of table rows