Как получить следующую / предыдущую запись в MySQL? - PullRequest
118 голосов
/ 19 сентября 2009

Допустим, у меня есть записи с идентификаторами 3, 4, 7, 9, и я хочу иметь возможность переходить от одного к другому с помощью навигации по следующим / предыдущим ссылкам. Проблема в том, что я не знаю, как получить запись с ближайшим более высоким ID.

Поэтому, когда у меня есть запись с идентификатором 4, мне нужно иметь возможность извлечь следующую существующую запись, которая будет равна 7. Запрос, вероятно, будет выглядеть примерно так:

SELECT * FROM foo WHERE id = 4 OFFSET 1

Как я могу получить следующую / предыдущую запись без извлечения всего набора результатов и итерации вручную?

Я использую MySQL 5.

Ответы [ 22 ]

2 голосов
/ 18 сентября 2017

Оптимизация подхода @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

изменить 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
2 голосов
/ 25 ноября 2014

Как получить следующую / предыдущую запись в MySQL & PHP?

Мой пример - получить только идентификатор

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;
  }
}
2 голосов
/ 01 мая 2018

Здесь у нас есть способ получить предыдущие и следующие записи, используя один запрос MySQL. Где 5 - идентификатор текущей записи.

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) )
1 голос
/ 23 мая 2015

Если вы хотите передать более одного id на ваш запрос и получить next_id для всех них ...

Назначьте cur_id в поле выбора, а затем передайте его подзапросу, получив next_id в поле выбора. А затем выберите просто next_id.

Использование длинного ответа для 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;
1 голос
/ 07 января 2015

Существует еще один прием, который можно использовать для отображения столбцов из предыдущих строк, используя любой порядок, который вы хотите, используя переменную, похожую на прием @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

По-видимому, столбцы выбора оцениваются по порядку, поэтому сначала будут выбраны сохраненные переменные, а затем обновлены переменные до новой строки (выбор их в процессе).

NB. Я не уверен, что это определенное поведение, но я использовал его, и оно работает.

1 голос
/ 06 апреля 2015
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
1 голос
/ 05 мая 2017

Если у вас есть столбец индекса, скажем id, вы можете вернуть предыдущий и следующий id в одном запросе sql. Заменить: 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 голосов
/ 21 января 2019

Вот мой ответ. Я выбрал идею из ' 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)

);

Следующим шагом является создание хранимой процедуры, которая отвечает за получение предыдущего идентификатора.

    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
0 голосов
/ 18 мая 2017

Мое решение, чтобы получить следующую и превью записи также вернуться к первой записи, если я по последней, и наоборот

Я не использую идентификатор, я использую название для хороших 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;
    }     
}
0 голосов
/ 30 мая 2015

Я думаю, чтобы иметь реальную следующую или предыдущую строку в таблице 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
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...