如何在 MySQL 中获取下一个/上一个记录?

假设我有 身份证 3,4,7,9的记录

我希望能够通过导航从一个到另一个通过下一个/前面的链接。

问题是,我不知道 如何获取最接近较高 ID 的记录

因此,当我有一个记录与 身份证 4,我需要能够获取下一个现有的记录,这将是 7

查询可能类似于

SELECT * FROM foo WHERE id = 4 OFFSET 1

如何在不获取整个结果集和手动迭代的情况下获取下一个/上一个记录?

我用的是 MySQL5。

257865 次浏览

从 foo 中选择 top 1 * ,其中 id > 4 order by id asc

下一步:

select * from foo where id = (select min(id) from foo where id > 4)

上一页:

select * from foo where id = (select max(id) from foo where id < 4)
SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1

除了 切姆卡扬库氏症解决方案:

下一张唱片:

SELECT * FROM foo WHERE id > 4 ORDER BY id LIMIT 1;

以往记录:

SELECT * FROM foo WHERE id < 4 ORDER BY id DESC LIMIT 1;

编辑: 由于这个答案最近得到了一些赞同,我真的想强调一下之前的 我的评论关于理解主键列并不意味着作为一个列进行排序,因为 MySQL 并不保证较高的、自动增量的值必须在以后添加。

如果您不关心这一点,只需要 id较高(或较低)的记录,那么这就足够了。只是不要使用这种方法来确定记录实际上是以后(还是以前)添加的。相反,可以考虑使用 datetime 列进行排序,例如。

我尝试做类似的事情,但是我需要按日期排序的结果,因为我不能依赖 ID 字段作为可排序的列。这是我想到的解决办法。

首先,我们找出表中所需记录的索引,当它按照我们想要的方式排序时:

SELECT row
FROM
(SELECT @rownum:=@rownum+1 row, a.*
FROM articles a, (SELECT @rownum:=0) r
ORDER BY date, id) as article_with_rows
WHERE id = 50;

然后将结果减2,将其放入极限语句中。例如,上面为我返回了21,所以我运行:

SELECT *
FROM articles
ORDER BY date, id
LIMIT 19, 3

提供您的主要记录,以及它的下一个和以前的记录给出您的说明订单。

我尝试将其作为单个数据库调用执行,但无法让 LIMIT 语句将变量作为参数之一。

上述所有解决方案都需要两个数据库调用。

select * from foo
where (
id = IFNULL((select min(id) from foo where id > 4),0)
or  id = IFNULL((select max(id) from foo where id < 4),0)
)

下一排

SELECT * FROM `foo` LIMIT number++ , 1

前排

SELECT * FROM `foo` LIMIT number-- , 1

下一行的样品

SELECT * FROM `foo` LIMIT 1 , 1
SELECT * FROM `foo` LIMIT 2 , 1
SELECT * FROM `foo` LIMIT 3 , 1

样品上一行

SELECT * FROM `foo` LIMIT -1 , 1
SELECT * FROM `foo` LIMIT -2 , 1
SELECT * FROM `foo` LIMIT -3 , 1


SELECT * FROM `foo` LIMIT 3 , 1
SELECT * FROM `foo` LIMIT 2 , 1
SELECT * FROM `foo` LIMIT 1 , 1

我和丹有同样的问题,所以我用了他的答案并改进了它。

首先选择行索引,这里没有什么不同。

SELECT row
FROM
(SELECT @rownum:=@rownum+1 row, a.*
FROM articles a, (SELECT @rownum:=0) r
ORDER BY date, id) as article_with_rows
WHERE id = 50;

现在使用两个单独的查询。例如,如果行索引为21,则选择下一条记录的查询将是:

SELECT *
FROM articles
ORDER BY date, id
LIMIT 21, 1

要选择以前的记录,请使用以下查询:

SELECT *
FROM articles
ORDER BY date, id
LIMIT 19, 1

请记住,对于第一行(行索引为1) ,限制将变为 -1,您将得到一个 MySQL 错误。您可以使用 if 语句来防止这种情况。只是不要选择任何东西,因为没有以前的记录无论如何。在最后一条记录的情况下,将有下一行,因此不会有结果。

还要记住,如果使用 DESC 进行排序,而不是使用 ASC,则选择下一行和上一行的查询仍然相同,但已切换。

使用@Dan 的方法,您可以创建 JOIN。

SELECT current_row.row, current_row.id, previous_row.row, previous_row.id
FROM (
SELECT @rownum:=@rownum+1 row, a.*
FROM articles a, (SELECT @rownum:=0) r
ORDER BY date, id
) as current_row
LEFT JOIN (
SELECT @rownum2:=@rownum2+1 row, a.*
FROM articles a, (SELECT @rownum2:=0) r
ORDER BY date, id
) as previous_row ON
(current_row.id = previous_row.id) AND (current_row.row = previous_row.row - 1)

如何在 MySQL 和 PHP 中获得下一个/上一个记录?

我的示例是只获取 id

function btn_prev(){


$id = $_POST['ids'];
$re = mysql_query("SELECT * FROM table_name WHERE your_id < '$id'  ORDER BY your_id DESC LIMIT 1");


if(mysql_num_rows($re) == 1)
{
$r = mysql_fetch_array($re);
$ids = $r['your_id'];
if($ids == "" || $ids == 0)
{
echo 0;
}
else
{
echo $ids;
}
}
else
{
echo 0;
}
}






function btn_next(){


$id = $_POST['ids'];
$re = mysql_query("SELECT * FROM table_name WHERE your_id > '$id'  ORDER BY your_id ASC LIMIT 1");


if(mysql_num_rows($re) == 1)
{
$r = mysql_fetch_array($re);
$ids = $r['your_id'];
if($ids == "" || $ids == 0)
{
echo 0;
}
else
{
echo $ids;
}
}
else
{
echo 0;
}
}

还有另一个技巧可以用来显示前面行中的列,可以使用任意顺序,使用类似于@row 技巧的变量:

SELECT @prev_col_a, @prev_col_b, @prev_col_c,
@prev_col_a := col_a AS col_a,
@prev_col_b := col_b AS col_b,
@prev_col_c := col_c AS col_c
FROM table, (SELECT @prev_col_a := NULL, @prev_col_b := NULL, @prev_col_c := NULL) prv
ORDER BY whatever

显然,选择列是按顺序计算的,因此这将首先选择保存的变量,然后将变量更新到新行(在过程中选择它们)。

注意: 我不确定这是否是定义好的行为,但是我已经用过了,而且很有效。

CREATE PROCEDURE `pobierz_posty`(IN iduser bigint(20), IN size int, IN page int)
BEGIN
DECLARE start_element int DEFAULT 0;
SET start_element:= size * page;
SELECT DISTINCT * FROM post WHERE id_users ....
ORDER BY data_postu DESC LIMIT size OFFSET start_element
END

试试这个例子。

create table student(id int, name varchar(30), age int);


insert into student values
(1 ,'Ranga', 27),
(2 ,'Reddy', 26),
(3 ,'Vasu',  50),
(5 ,'Manoj', 10),
(6 ,'Raja',  52),
(7 ,'Vinod', 27);


SELECT name,
(SELECT name FROM student s1
WHERE s1.id < s.id
ORDER BY id DESC LIMIT 1) as previous_name,
(SELECT name FROM student s2
WHERE s2.id > s.id
ORDER BY id ASC LIMIT 1) as next_name
FROM student s
WHERE id = 7;

注意: 如果找不到 价值,它将返回 无效

在上面的例子中, 之前的 值将是 拉贾,而 下一个值将是 无效,因为没有下一个值。

如果您想要 供给多于一个 id到您的查询,并得到 next_id为所有这些..。

在选择字段中分配 cur_id,然后将其提供给子查询,以获取选择字段中的 next_id。然后选择 next_id

使用长回答来计算 next_id:

select next_id
from (
select id as cur_id, (select min(id) from `foo` where id>cur_id) as next_id
from `foo`
) as tmp
where next_id is not null;

我认为要在 SQL 表中实现下一行或上一行,我们需要等于(< 或 >)的实值,如果需要更改排序表中行的位置,则返回多个实值。

我们需要值 $position来搜索 neighbours行 在我的表中,我创建了一个列‘ position’

获取所需行的 SQL 查询是:

接下来:

SELECT *
FROM `my_table`
WHERE id = (SELECT (id)
FROM my_table
WHERE position = ($position+1))
LIMIT 1

前情提要:

 SELECT *
FROM my_table
WHERE id = (SELECT (id)
FROM my_table
WHERE `position` = ($position-1))
LIMIT 1

对于结果相同的情况,这是通用的解决方案。

<?php
$your_name1_finded="somethnig searched"; //$your_name1_finded must be finded in previous select


$result = db_query("SELECT your_name1 FROM your_table WHERE your_name=your_condition ORDER BY your_name1, your_name2"); //Get all our ids


$i=0;
while($row = db_fetch_assoc($result)) { //Loop through our rows
$i++;
$current_row[$i]=$row['your_name1'];// field with results
if($row['your_name1'] == $your_name1_finded) {//If we haven't hit our current row yet
$yid=$i;
}
}
//buttons
if ($current_row[$yid-1]) $out_button.= "<a  class='button' href='/$your_url/".$current_row[$yid-1]."'>BUTTON_PREVIOUS</a>";
if ($current_row[$yid+1]) $out_button.= "<a  class='button' href='/$your_url/".$current_row[$yid+1]."'>BUTTON_NEXT</a>";


echo $out_button;//display buttons
?>

如果有一个索引列,比如 id,那么可以在一个 sql 请求中返回前一个 id 和下一个 id。 用您的值替换: id

SELECT
IFNULL((SELECT id FROM table WHERE id < :id ORDER BY id DESC LIMIT 1),0) as previous,
IFNULL((SELECT id FROM table WHERE id > :id ORDER BY id ASC LIMIT 1),0) as next

我的解决方案获得下一个和预览记录 如果我是倒数第一张唱片,反之亦然

我没有用 id,我用的是 nice url 的标题

我用的是 Codeigniter HMVC

$id = $this->_get_id_from_url($url);


//get the next id
$next_sql = $this->_custom_query("select * from projects where id = (select min(id) from projects where id > $id)");
foreach ($next_sql->result() as $row) {
$next_id = $row->url;
}


if (!empty($next_id)) {
$next_id = $next_id;
} else {
$first_id = $this->_custom_query("select * from projects where id = (SELECT MIN(id) FROM projects)");
foreach ($first_id->result() as $row) {
$next_id = $row->url;
}
}


//get the prev id
$prev_sql = $this->_custom_query("select * from projects where id = (select max(id) from projects where id < $id)");
foreach ($prev_sql->result() as $row) {
$prev_id = $row->url;
}


if (!empty($prev_id)) {
$prev_id = $prev_id;
} else {
$last_id = $this->_custom_query("select * from projects where id = (SELECT MAX(id) FROM projects)");
foreach ($last_id->result() as $row) {
$prev_id = $row->url;
}
}

优化@Don 方法只使用一个查询

SELECT * from (
SELECT
@rownum:=@rownum+1 row,
CASE a.id WHEN 'CurrentArticleID' THEN @currentrow:=@rownum ELSE NULL END as 'current_row',
a.*
FROM articles a,
(SELECT @currentrow:=0) c,
(SELECT @rownum:=0) r
ORDER BY `date`, id  DESC
) as article_with_row
where row > @currentrow - 2
limit 3

使用当前文章 ID 更改 CurrentArticleID,如

SELECT * from (
SELECT
@rownum:=@rownum+1 row,
CASE a.id WHEN '100' THEN @currentrow:=@rownum ELSE NULL END as 'current_row',
a.*
FROM articles a,
(SELECT @currentrow:=0) c,
(SELECT @rownum:=0) r
ORDER BY `date`, id  DESC
) as article_with_row
where row > @currentrow - 2
limit 3

在这里,我们有一种使用单个 MySQL 查询来获取前面和下一个记录的方法。 其中5是当前记录的 id。

select * from story where catagory=100 and  (
id =(select max(id) from story where id < 5 and catagory=100 and order by created_at desc)
OR
id=(select min(id) from story where id > 5 and catagory=100 order by created_at desc) )

这就是我的答案。我从“ 不错的业余爱好者”中提取了一个想法,并添加了检查 身份证是否介于 min (id)和 max (id)之间的部分。下面是创建表的部分。

CREATE TABLE Users (
UserID int NOT NULL auto_increment,
UserName varchar(45),
UserNameID varchar(45),
PRIMARY KEY (UserID)

);

下一步是创建一个负责获取前一个 id 的存储过程。

    CREATE DEFINER=`root`@`localhost` PROCEDURE `printPreviousIDbySelectedIDUser`(
IN ID int,
IN search_name varchar(45)
)
BEGIN
SELECT CONCAT(ns.UserID) AS 'Previous ID' from Users ns
where ns.UserName=search_name AND ns.UserID IN (select min(ns.UserID) from Users ns where ns.UserID > ID
union select max(ns.UserID) from Users ns where  ns.UserID < ID) LIMIT 1 ;
END

如果索引是排序的,那么第一个方法是好的,但是如果索引不是排序的,那么第一个方法就是好的。例如,如果您有索引: 1、2、7,并且您需要以这种方式获得索引号2,以便更好地使用另一种方法。

    CREATE DEFINER=`root`@`localhost` PROCEDURE `getPreviousUserID`(
IN ID int,
IN search_name varchar(45)
)
BEGIN
SELECT CONCAT(ns.UserID) AS 'Previous ID' from Users ns
WHERE ns.UserName=search_name AND  ns.UserID < ID   ORDER BY ns.UserID DESC LIMIT 1;
END

100% 正常

SELECT * FROM `table` where table_id < 3 ORDER BY `table_id` DESC limit 1

一种在表中获取下一个和上一个 id 的方法,如果没有下一个 id,我选择第一个。之前的身份也一样

SELECT id FROM foo
WHERE (
id = IFNULL((SELECT min(id) FROM medialibrary WHERE id > ?),(SELECT id FROM foo LIMIT 1))
or
id = IFNULL((SELECT max(id) FROM medialibrary WHERE id < ?),(SELECT id FROM fooORDER BY id DESC LIMIT 1))