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

Jak*_*old 121 mysql sql

假设我有ID 3,4,7,9的记录,我希望能够通过下一个/上一个链接导航从一个到另一个.问题是,我不知道如何获取最近的更高ID的记录.

因此,当我有一个ID为4的记录时,我需要能够获取下一个现有记录,这将是7.查询可能看起来像

SELECT * FROM foo WHERE id = 4 OFFSET 1
Run Code Online (Sandbox Code Playgroud)

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

我正在使用MySQL 5.

lon*_*eck 237

下一个:

select * from foo where id = (select min(id) from foo where id > 4)
Run Code Online (Sandbox Code Playgroud)

以前:

select * from foo where id = (select max(id) from foo where id < 4)
Run Code Online (Sandbox Code Playgroud)

  • 我认为子查询应该是(从foo中选择min(id),其中id> 4)和(从foo中选择max(id),其中id <4). (5认同)
  • 这不是解决方案,因为如果您从“ foo”中删除行,将会发生什么?:P (2认同)

Dec*_*ler 134

除了cemkalyoncu的解决方案:

下一条记录:

SELECT * FROM foo WHERE id > 4 ORDER BY id LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

之前的纪录:

SELECT * FROM foo WHERE id < 4 ORDER BY id DESC LIMIT 1;
Run Code Online (Sandbox Code Playgroud)

编辑:由于这个答案最近得到了一些upvotes,我真的想强调之前的关于理解主键列不是要排序的列的评论,因为MySQL不保证更高,自动递增,值必须在以后添加.

如果你不关心这个,只需要更高(或更低)的记录,id那么这就足够了.只是不要将其用作确定记录是否实际在以后(或更早)添加的方法.例如,请考虑使用datetime列进行排序.


sud*_*dip 56

以上所有解决方案都需要两次数据库调用 下面的sql代码将两个sql语句合并为一个.

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)
      )    
Run Code Online (Sandbox Code Playgroud)

  • 绝对是最好的解决方案.快速和一次性查询. (2认同)

Cem*_*ncu 19

SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1
Run Code Online (Sandbox Code Playgroud)

  • +1我认为这是最干净的解决方案。但 LIMIT 子句应该放在最后: SELECT * FROM foo WHERE id &gt; 4 ORDER BY id LIMIT 1 (2认同)

Dan*_*Dan 11

我试图做类似的事情,但我需要按日期排序的结果,因为我不能依赖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;
Run Code Online (Sandbox Code Playgroud)

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

SELECT * 
FROM articles
ORDER BY date, id
LIMIT 19, 3
Run Code Online (Sandbox Code Playgroud)

根据您所声明的订单,为您提供主要记录以及下一个和之前的记录.

我尝试将其作为单个数据库调用来执行,但无法获取LIMIT语句将变量作为其中一个参数.


Edu*_*les 7

使用@Dan的方法,您可以创建JOIN.只需为每个子查询使用不同的@variable.

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)
Run Code Online (Sandbox Code Playgroud)


Ran*_*ddy 7

试试这个例子.

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; 
Run Code Online (Sandbox Code Playgroud)

注意:如果未找到,则返回null.

在上面的示例中, Previous值将为Raja,Next值将为null,因为没有下一个值.