假设我有ID为3、4、7、9的记录,并且我希望能够通过下一个/上一个链接导航到另一个。问题是,我不知道如何获取具有最近的较高ID的记录。
因此,当我有一个ID为4的记录时,我需要能够获取下一个现有记录,即7。查询可能看起来像
SELECT * FROM foo WHERE id = 4 OFFSET 1
如何获取下一个/上一个记录,而不获取整个结果集并手动进行迭代?
我正在使用MySQL 5。
假设我有ID为3、4、7、9的记录,并且我希望能够通过下一个/上一个链接导航到另一个。问题是,我不知道如何获取具有最近的较高ID的记录。
因此,当我有一个ID为4的记录时,我需要能够获取下一个现有记录,即7。查询可能看起来像
SELECT * FROM foo WHERE id = 4 OFFSET 1
如何获取下一个/上一个记录,而不获取整个结果集并手动进行迭代?
我正在使用MySQL 5。
Answers:
下一个:
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的解决方案:
下一条记录:
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列进行排序。
以上所有解决方案都需要两个数据库调用。下面的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)
)
DISTINCT
之前添加*
将使它变得更好,也就是说,当然id
可以具有0
价值。
id
而不是两个。
SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1
SELECT * FROM foo WHERE id<4 ORDER BY id DESC LIMIT 1
对于previouse记录
我试图做类似的事情,但是我需要按日期排序的结果,因为我不能依赖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,将其放入limit语句中。例如,上面为我返回了21,所以我运行:
SELECT *
FROM articles
ORDER BY date, id
LIMIT 19, 3
给定您的主要记录,以及指定顺序的下一个和上一个记录。
我试图将其作为单个数据库调用来完成,但是无法获得LIMIT语句来将变量作为其参数之一。
试试这个例子。
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;
注意:如果未找到值,则它将返回null。
在上面的示例中,“ 上一个”值为“ Raja”,Next值将为null,因为没有下一个值。
使用@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)
current
-- current_row
&&previous
-> previous_row
。
下一行
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
我遇到了与Dan相同的问题,因此我使用了他的答案并对它进行了改进。
首先选择行索引,这里没有什么不同。
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进行排序,则查询以选择下一行和上一行仍然相同,但已切换。
这是具有更多相同结果的条件的通用解决方案。
<?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
?>
在这里,我们有一种使用单个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) )
如何获取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;
}
}
优化@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
您还可以使用另一种技巧来显示上一行的列,使用所需的任何顺序,并使用类似于@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
如果您有一个索引列,例如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
如果我排在最后,反之亦然,获得下一个和预览记录的解决方案也可以返回到第一条记录
我没有使用ID,而是将标题用于了不错的网址
我正在使用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;
}
}
这是我的答案。我从“ Decent Dabbler ”中提出了一个想法,并添加了检查id是否在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
我认为要在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