2009-09-18 89 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 
相關問題