如何获取MySQL中的下一个/上一个logging?

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

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

SELECT * FROM foo WHERE id = 4 OFFSET 1 

我怎样才能获取下一个/上一个logging,而无需获取整个结果集和手动迭代?

我正在使用MySQL 5。

下一个:

 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) 

除了cemkalyoncu的解决scheme:

下一个logging:

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

之前的纪录:

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

编辑:由于这个答案最近得到了一些upvotes,我真的想强调我早些时候做的关于理解主键列不意味着要sorting的列的评论,因为MySQL不保证更高的自动递增,值必须在稍后添加。

如果你不关心这个,只需要更高(或更低)的logging,那么这就足够了。 只是不要用这个方法来确定一个logging是否实际上是在稍后(或之前)添加的。 相反,考虑使用一个date时间列进行sorting。

以上所有解决scheme都需要两次数据库调用 下面的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) ) 
 SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1 

我试图做类似的事情,但我需要按datesorting的结果,因为我不能依靠ID字段作为一个可sorting的列。 这是我提出的解决scheme。

首先我们find表中所需logging的索引,当它按照我们的要求进行sorting时:

 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 

给你你的主要logging,以及它的下一个和以前的logging给定的顺序。

我试图做一个单一的数据库调用,但不能获取LIMIT语句作为其参数之一的variables。

我有和丹一样的问题,所以我用他的答案和改进。

首先select行索引,这里没什么不同。

 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下一个logging的查询将是:

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

要select以前的logging使用此查询:

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

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

另外请记住,如果使用DESC进行sorting,而不是ASC,则查询select下一行和前一行仍然是相同的,但切换。

使用@Dan的方法,你可以创buildJOIN。 只要为每个子查询使用不同的@variable。

 SELECT current.row, current.id, previous.row, previous.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) 

试试这个例子。

 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; 

注意:如果没有find ,则返回null

在上面的例子中, Previous值是RajaNext值是null,因为没有下一个值。

下一行

 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 

如何获取MySQL和PHP中的下一个/上一个logging?

我的例子是只获得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; } } 

这是通用解决scheme的条件更相同的结果。

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

还有一个技巧可以用来显示前一行的列,使用类似于@row技巧的variables:

 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 

显然,select列是按顺序评估的,所以这将首先select已保存的variables,然后将variables更新到新行(在过程中select它们)。

注意:我不确定这是否是已定义的行为,但是我已经使用了它,并且工作正常。

如果你想饲喂多个id到你的查询,并得到他们所有的next_id

在select字段中分配cur_id ,然后将其提供给在select字段中获取next_id子查询。 然后selectnext_id

使用longneck答案来计算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; 
 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 

如果你有一个索引列,比如id,你可以在一个sql请求中返回上一个和下一个id。 用您的值replace: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 

我的解决scheme获得下一个和预览logging也回到第一个logging,如果我是最后一个,反之亦然

我没有使用ID我使用标题的好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 

从fooselecttop 1 *,其中id> 4,顺序为id asc

我认为在SQL表中有真正的下一行或前一行,如果需要更改sorting表中的行的位置,我们需要相同的实际值(<或>)返回多个行。

我们需要值$position来searchneighbours行在我的表中,我创build了一个“位置”

和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