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



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



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



SELECT * FROM foo WHERE id = 4 OFFSET 1


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



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

3682   20  

20 ответов:

следующий:

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 это!--5--> устранение:

следующая запись:

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

предыдущая запись:

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

edit: так как этот ответ получал несколько повышений в последнее время, я действительно хочу подчеркнуть комментарий, который я составила ранее о понимании того, что первичный ключ colum не предназначен как столбец для сортировки, потому что MySQL не гарантирует, что более высокие, автоматически увеличенные значения обязательно добавляются в a позднее время.

Если вас это не волнует, а просто нужна запись с более высоким (или более низким) 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)
      )    
SELECT * FROM foo WHERE id>4 ORDER BY id LIMIT 1

Я пытался сделать что-то подобное, но мне нужны были результаты, упорядоченные по дате, так как я не могу полагаться на поле 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.

В приведенном выше примере, значение будет Раджа и далее значение будет 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

используя подход @Dan, вы можете создавать объединения. Просто используйте другую переменную @для каждого подзапроса.

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)

у меня была та же проблема, что и у Дэна, поэтому я использовал его ответ и улучшил его.

Сначала выберите индекс строки, здесь ничего не изменилось.

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 & 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;
  }
}

здесь у нас есть способ получить предыдущие и следующие записи с помощью одного запроса 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) )

есть еще один трюк, который вы можете использовать, чтобы показать столбцы из предыдущих строк, используя любой порядок, который вы хотите, используя переменную, похожую на @ Row trick:

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: я не уверен, что это определенное поведение, но я использовал его, и он работает.

если вы хотите кормить более одного 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;
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, вы можете вернуть предыдущий и следующий id в одном запросе sql. Замена :удостоверение с вашим значением

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

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

изменить Currenttarticleid с текущим идентификатором статьи, Как

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

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

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

выберите top 1 * from foo where id > 4 order by id asc

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

Comments

    Ничего не найдено.