2009-09-18 91 views
97

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

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

SELECT * FROM foo WHERE id = 4 OFFSET 1 

我怎样才能下次提取/以前的记录没有获取整个结果集并手动迭代?

我使用MySQL 5

+5

你不应该依赖的ID进行排序(即:假设你的ID是一个AUTO_INCREMENT列)。您应该在表格中创建另一个明确描述排序顺序的列。 – 2009-09-18 21:10:07

回答

196

下一个:

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) 
+3

我认为子查询应该是(从foo中选择min(id),其中id> 4)和(从foo中选择max(id),其中id <4)。 – 2009-09-18 21:16:16

+0

你是对的,我忘记了FROM子句。感谢您指出。 :) – longneck 2009-09-20 15:33:20

+1

这不是解决方案,因为如果您从“foo”中删除行,会发生什么情况? :P – 2014-02-24 08:36:02

-1

选择前1 *从foo其中ID> 4 ORDER BY ID ASC

+2

mysql不支持TOP – longneck 2009-09-18 21:04:25

+2

Top 1 *在mysql中不起作用。 – 2009-09-18 21:05:16

+1

我的无知抱歉 – Gratzy 2009-09-18 21:06:03

15
SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1 
+0

+1我认为这是最干净的解决方案。但LIMIT子句应该最后一个:SELECT * FROM foo WHERE id> 4 ORDER BY id LIMIT 1 – 2009-09-18 21:18:21

+0

and'SELECT * FROM foo WHERE id <4 ORDER BY id DESC LIMIT 1' for previouse record – fwonce 2015-03-12 03:43:12

119

另外,到cemkalyoncu's解决方案:

下一个记录:

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

此前的纪录:

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

编辑:由于这已经回答了最近获得的一些upvotes,我真的想强调comment I made早些时候关于理解主键列并不意味着要排序的列,因为MySQL不保证稍后添加更高的自动递增值即

如果你不关心这个,只需要更高(或更低)id的记录,那么这就足够了。只是不要使用这种方法来确定记录是否实际上是晚些时候(或更早)添加的。相反,考虑使用日期时间列进行排序。

9

我试图做类似的事情,但我需要按日期排序的结果,因为我不能依靠ID字段作为可排序的列。这是我提出的解决方案。

首先,我们找出所需的记录的索引表中,当它的排序,因为我们希望:

SELECT row 
FROM 
(SELECT @rownum:[email protected]+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语句将变量作为其参数之一。

+0

我对你的方法感兴趣。如果你还需要做一个JOIN呢?说,从文章a JOIN作者b ON b.this = a.that。在我看来,JOIN混淆了排序。这里有一个例子http://pastebin.com/s7R62GYV – idrarig 2013-09-02 14:20:46

+1

要做一个JOIN,你需要定义两个不同的@变量。 ' SELECT current.row,current.id,previous.row,previous.id FROM(SELECT @rownum:= @ ROWNUM + 1行中,* FROM 物品,(SELECT @rownum:= 0 )R ORDER BY日期,ID )作为CURRENT_ROW LEFT JOIN( SELECT @ rownum2:= @ rownum2 + 1行中,* FROM物品,(SELECT @ rownum2:= O)R ORDER BY日期,和前一行ON (current_row.id = previous_row.id)AND(current_row.row = previous_row.row -1) ' – 2014-10-31 18:56:20

44

以上所有解决方案都需要两次数据库调用。下面的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) 
    )  
+2

绝对是最好的解决方案。快速和全部在一个查询。 – daemon 2013-05-06 12:37:14

+0

即使在更复杂的查询中也可以完成工作! – taiar 2014-07-25 16:42:05

+0

在'*'之前加上'DISTINCT'会使它更好,当然如果'id'可以有'0'的值。 – Ejaz 2015-06-15 21:29:58

3

下一行

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 
3

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

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

SELECT row 
FROM 
(SELECT @rownum:[email protected]+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,您的查询选择下一个和以前的行仍然是相同的,但切换。

4

使用@丹的做法,您可以创建连接。每个子查询只需使用一个不同的@variable。

SELECT current.row, current.id, previous.row, previous.id 
FROM (
    SELECT @rownum:[email protected]+1 row, a.* 
    FROM articles a, (SELECT @rownum:=0) r 
    ORDER BY date, id 
) as current_row 
LEFT JOIN (
    SELECT @rownum2:[email protected]+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) 
+0

正是我所需要的,谢谢。请注意,您的选择不正确,“current” - >'current_row'&'previous' - >'previous_row'。 – 2014-12-02 14:10:45

2

如何获取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; 
    } 
} 
+0

不要把代码标签内的文字! – 2015-08-19 03:45:04

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 

显然,选择列按顺序进行评估,所以这将首先选择保存的变量,然后将变量更新到新行(在过程中选择它们)。

注:我不知道,这是定义的行为,但我用它和它的作品。

0
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 
+6

欢迎来到StackOverflow。完全由代码组成的答案很少有用。请考虑提供一些关于你的代码在做什么的解释。代码文档和/或英文中的变量名称也会有所帮助。 – 2015-04-06 20:35:51

4

试试这个例子。

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; 

注:如果没有找到,那么它将返回

在上述例子中, 上一页值将是拉加接着值将是零因为没有下一个值。

0

如果你想养活不止一个id到您的查询,并得到next_id为所有的人......

分配cur_id在您选择字段,然后喂它子查询得到next_id选择字段内。然后选择next_id

使用longneck答案calc下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; 
-2

我认为在SQL表中的真正的下一个或前行,我们需要平等的真正价值,(<或>)返回多于一个,如果你需要更改排序表中的行的位置。

我们需要的值$position搜索neighbours行 在我的表我创建了一列“位置”

和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 
+0

如果一行已被删除,则会中断。例如:如果ID是1,2,6,7,8。 – 2017-02-01 22:41:26

2

这是通用解决方案,其条件更加相同。

<?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 
?> 
0

如果你有一个索引列,比如说id,你可以在一个sql请求中返回上一个和下一个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 
0

我的解决方案,以获得下和预览记录 也回到第一个记录,如果我被最后反之亦然

我不是使用我使用的标题漂亮的URL

的ID我用笨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; 
    }  
} 
0

优化@Don approac小时,只使用一个查询

SELECT * from (
    SELECT 
    @rownum:[email protected]+1 row, 
    CASE a.id WHEN 'CurrentArticleID' THEN @currentrow:[email protected] 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 

变化CurrentArticleID与当前的文章ID喜欢

SELECT * from (
    SELECT 
    @rownum:[email protected]+1 row, 
    CASE a.id WHEN '100' THEN @currentrow:[email protected] 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 
相关问题