Как найти следующую строку в sql

next:

select * from foo where id = (select min(id) from foo where id > 4)

previous:

select * from foo where id = (select max(id) from foo where id < 4)

Vimalnath's user avatar

Vimalnath

6,3582 gold badges26 silver badges47 bronze badges

answered Sep 18, 2009 at 21:03

longneck's user avatar

8

In addition to cemkalyoncu’s solution:

next record:

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

previous record:

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

edit: Since this answer has been getting a few upvotes lately, I really want to stress the comment I made earlier about understanding that a primary key colum is not meant as a column to sort by, because MySQL does not guarantee that higher, auto incremented, values are necessarily added at a later time.

If you don’t care about this, and simply need the record with a higher (or lower) id then this will suffice. Just don’t use this as a means to determine whether a record is actually added later (or earlier). In stead, consider using a datetime column to sort by, for instance.

Community's user avatar

answered Sep 18, 2009 at 21:23

Decent Dabbler's user avatar

Decent DabblerDecent Dabbler

22.5k8 gold badges73 silver badges106 bronze badges

1

All the above solutions require two database calls. The below sql code combine two sql statements into one.

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

4

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

answered Sep 18, 2009 at 21:05

Cem Kalyoncu's user avatar

Cem KalyoncuCem Kalyoncu

14.1k4 gold badges40 silver badges62 bronze badges

2

I was attempting to do something similar to this, but I needed the results ordered by date since I can’t rely on the ID field as a sortable column. Here’s the solution I came up with.

First we find out the index of the desired record in the table, when it’s sorted as we want:

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;

Then decrement the result by 2 put it in the limit statement. For example the above returned 21 for me so I run:

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

Gives you your primary record along with it’s next and previous records given your stated order.

I tried to do it as a single database call, but couldn’t get the LIMIT statement to take a variable as one of it’s parameters.

answered Oct 30, 2012 at 10:05

Dan's user avatar

DanDan

2,17219 silver badges29 bronze badges

2

Try this example.

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; 

Note: If value is not found then it will return null.

In the above example,
Previous value will be Raja and Next value will be null because there is no next value.

answered May 7, 2015 at 5:07

Ranga Reddy's user avatar

Ranga ReddyRanga Reddy

2,8964 gold badges29 silver badges41 bronze badges

Using @Dan ‘s approach, you can create JOINs. Just use a different @variable for each sub query.

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)

Dharmang's user avatar

Dharmang

2,99834 silver badges38 bronze badges

answered Oct 31, 2014 at 19:04

Eduardo Moralles's user avatar

3

Next row

SELECT * FROM `foo` LIMIT number++ , 1

Previous row

SELECT * FROM `foo` LIMIT number-- , 1

sample next row

SELECT * FROM `foo` LIMIT 1 , 1
SELECT * FROM `foo` LIMIT 2 , 1
SELECT * FROM `foo` LIMIT 3 , 1

sample previous row

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

kleopatra's user avatar

kleopatra

50.9k28 gold badges99 silver badges209 bronze badges

answered Nov 17, 2013 at 22:43

IDALICIUS's user avatar

IDALICIUSIDALICIUS

411 silver badge1 bronze badge

I had the same problem as Dan, so I used his answer and improved it.

First select the row index, nothing different here.

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;

Now use two separate queries. For example if the row index is 21, the query to select the next record will be:

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

To select the previous record use this query:

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

Keep in mind that for the first row (row index is 1), the limit will go to -1 and you will get a MySQL error. You can use an if-statement to prevent this. Just don’t select anything, since there is no previous record anyway. In the case of the last record, there will be next row and therefor there will be no result.

Also keep in mind that if you use DESC for ordering, instead of ASC, you queries to select the next and previous rows are still the same, but switched.

answered Dec 15, 2013 at 15:45

magnetronnie's user avatar

This is universal solution for conditions wiht more same results.

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

answered Nov 17, 2016 at 1:13

asdf2017's user avatar

Here we have a way to fetch previous and next records using single MySQL query.
Where 5 is the id of current record.

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

answered May 1, 2018 at 10:41

Jaskaran Singh's user avatar

0

How to get next/previous record in MySQL & PHP?

My example is to get the id only

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

Cary Bondoc's user avatar

Cary Bondoc

2,8834 gold badges37 silver badges58 bronze badges

answered Nov 25, 2014 at 3:30

1

Optimising @Don approach to use only One Query

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

change CurrentArticleID with current article ID like

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

answered Sep 18, 2017 at 9:57

Zeeshan Anjum's user avatar

1

There’s another trick you can use to show columns from previous rows, using any ordering you want, using a variable similar to the @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

Apparently, the select columns are evaluated in order, so this will first select the saved variables, and then update the variables to the new row (selecting them in the process).

NB: I’m not sure that this is defined behaviour, but I’ve used it and it works.

answered Jan 7, 2015 at 14:49

Willem M.'s user avatar

Willem M.Willem M.

4645 silver badges8 bronze badges

If you want to feed more than one id to your query and get next_id for all of them…

Assign cur_id in your select field and then feed it to subquery getting next_id inside select field. And then select just next_id.

Using longneck answer to 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;

answered May 23, 2015 at 11:24

Unicorn's user avatar

UnicornUnicorn

1,3771 gold badge14 silver badges24 bronze badges

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

Ultimater's user avatar

Ultimater

4,6182 gold badges29 silver badges43 bronze badges

answered Apr 6, 2015 at 20:28

Piotr Kos's user avatar

1

If you have an index column, say id, you can return previous and next id in one sql request.
Replace :id with your value

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

answered May 5, 2017 at 6:41

Patrice Flao's user avatar

Here is my answer. I pick up an idea from ‘Decent Dabbler‘ and add the part that is checking if id is between min(id) and max(id). Here is the part for creating my table.

CREATE TABLE Users (
UserID int NOT NULL auto_increment,
UserName varchar(45),
UserNameID varchar(45),
PRIMARY KEY (UserID)

);

Next step is creating a stored procedure that is responsible for getting the previous 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

The first method is good if the indexes are sorted, but if they are not. For example, if you have indexes: 1,2,7 and you need to get index number 2 in this way much better to use another approach.

    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

answered Jan 21, 2019 at 12:19

Dennis's user avatar

DennisDennis

1012 silver badges10 bronze badges

2

A way to get next and previous id in the table and if there is no next id i select the first one.Same for the previous id

SELECT id FROM foo
    WHERE ( 
    id = IFNULL((SELECT min(id) FROM medialibrary WHERE id > ?),(SELECT id FROM foo LIMIT 1)) 
    or 
    id = IFNULL((SELECT max(id) FROM medialibrary WHERE id < ?),(SELECT id FROM fooORDER BY id DESC LIMIT 1))

answered Aug 20, 2021 at 13:29

fatoon's user avatar

fatoonfatoon

231 silver badge8 bronze badges

My solution to get the next and previews record
also to get back to the first record if i’m by the last and vice versa

I’m not using the id i’m using the title for nice url’s

I’m using 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;
    }     
}

answered May 18, 2017 at 3:00

toiglicher's user avatar

1

100 % working

SELECT * FROM `table` where table_id < 3 ORDER BY `table_id` DESC limit 1

Mark Rotteveel's user avatar

answered Jun 22, 2019 at 11:08

Ragul's user avatar

RagulRagul

111 bronze badge

I think to have the real next or previous row in SQL table we need the real value with equal, (< or >) return more than one if you need to change position of row in a ordering table.

we need the value $position to search the neighbours row
In my table I created a column ‘position’

and SQL query for getting the needed row is :

for next :

SELECT * 
FROM `my_table` 
WHERE id = (SELECT (id) 
            FROM my_table 
            WHERE position = ($position+1)) 
LIMIT 1

for previous:

 SELECT * 
 FROM my_table 
 WHERE id = (SELECT (id) 
             FROM my_table 
             WHERE `position` = ($position-1)) 
 LIMIT 1

Ram's user avatar

Ram

3,08410 gold badges40 silver badges56 bronze badges

answered May 30, 2015 at 17:10

Roussos's user avatar

1

Select top 1 * from foo where id > 4 order by id asc

answered Sep 18, 2009 at 21:03

Gratzy's user avatar

GratzyGratzy

9,1744 gold badges29 silver badges45 bronze badges

1

В этом учебном пособии вы узнаете, как использовать Oracle/PLSQL функцию LEAD с синтаксисом и примерами.

Описание

Oracle/PLSQL функция LEAD является аналитической функцией, что позволяет запрашивать более одной строки в таблице, в то же время, не имея для присоединения к себе таблицы. Возвращает значения из следующей строки в таблице. Для возврата значения из предыдущего ряда, попробуйте использовать функцию LAG.

Синтаксис

Синтаксис Oracle/PLSQL функции LEAD:

LEAD ( expression [, offset [, default] ] )
over ( [ query_partition_clause ] order_by_clause )

Параметры или аргументы

expression выражение, которое может содержать другие встроенные функции, но не может содержать аналитические функции.

offset – необязательный. Это физические смещение от текущей строки в таблице. Если этот параметр не указан, то по умолчанию 1.

default – необязательный. Это значение, которое возвращается, если offset выходит за границы таблицы. Если этот параметр не указан, то по умолчанию Null.

query_partition_clause – необязательный. Он используется для разделения результатов на группы на основе одного или нескольких выражений.

order_by_clause – необязательный. Он используется для упорядочения данных в каждом разделе.

Функция LEAD возвращает значения из следующей строки таблицы.

Применение

Функцию LEAD можно использовать в следующих версиях Oracle/PLSQL:

  • Oracle 12c, Oracle 11g, Oracle 10g, Oracle 9i, Oracle 8i

Пример

Функция LEAD может быть использована в Oracle/PLSQL.

Рассмотрим пример. Если у нас есть таблица orders, которая содержит следующие данные:

ORDER_DATE PRODUCT_ID QTY
25/09/2007 1000 20
26/09/2007 2000 15
27/09/2007 1000 8
28/09/2007 2000 12
29/09/2007 2000 2
30/09/2007 1000 4

И мы запустим следующий запрос:

SELECT product_id,

       order_date,

       LEAD (order_date,1) over (ORDER BY order_date) AS next_order_date

  FROM orders;

То получим следующий результат:

PRODUCT_ID ORDER_DATE NEXT_ORDER_DATE
1000 25/09/2007 26/09/2007
2000 26/09/2007 27/09/2007
1000 27/09/2007 28/09/2007
2000 28/09/2007 29/09/2007
2000 29/09/2007 30/09/2007
1000 30/09/2007

Так как мы использовали offset 1, запрос возвращает следующий ORDER_DATE.

Если бы мы использовали offset 2 вместо этого, он бы вернул ORDER_DATE 2 заказами позже. Если бы мы использовали offset 3, то это вернуло бы ORDER_DATE на 3 заказа позже …. и так далее.

Если мы захотим узнать только заказы для данного product_id, выполним следующий SQL запрос:

SELECT product_id,

   order_date,

   LEAD (order_date,1) over (ORDER BY order_date) AS next_order_date

  FRON orders

WHERE product_id = 2000;

Запрос вернет следующий результат:

PRODUCT_ID ORDER_DATE NEXT_ORDER_DATE
2000 26/09/2007 28/09/2007
2000 28/09/2007 29/09/2007
2000 29/09/2007

В этом примере, вернется следующий ORDER_DATE для product_id = 2000 и будут проигнорированы все другие заказы.

Использование partitions
Теперь давайте посмотрим на более сложный пример, в котором мы используем параметр запроса partition для возврата следующей order_date для каждого product_id.

Введите следующий оператор SQL:

SELECT product_id,

   order_date,

       LEAD (order_date,1) OVER (PARTITION BY product_id ORDER BY order_date) AS next_order_date

  FROM orders;

ORDER_DATE PRODUCT_ID QTY
1000 2007/09/25 2007/09/27
1000 2007/09/27 2007/09/30
1000 2007/09/30 NULL
2000 2007/09/26 2007/09/28
2000 2007/09/28 2007/09/29
2000 2007/09/29 NULL

В этом примере функция LEAD разделит результаты по product_id, а затем отсортирует по order_date, как указано в PARTITION BY product_id ORDER BY order_date. Это означает, что функция LEAD будет оценивать значение order_date, только если product_id совпадает с product_id текущей записи. Когда встречается новый product_id, функция LEAD перезапускает свои вычисления и использует соответствующий раздел product_id.

Как вы можете видеть, третья запись в наборе результатов имеет значение NULL для next_order_date, потому что это последняя запись для раздела, где product_id равен 1000 (отсортировано по order_date). Это также верно для 6-й записи, где product_id равен 2000.



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

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

SELECT * FROM foo WHERE id = 4 OFFSET 1

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

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


3185  


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:[email protected]+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:[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)

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

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

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

Это универсальное решение для условий с более одинаковые результаты.

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

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

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

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

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

У меня есть таблица, называемая products в базе данных MySQL. products выглядят примерно так:

 id name din strength active deleted 1 APA TEST 00246374 25 1 0 4 APA BOB 00246375 50 1 0 5 APA TIRE 00246888 50 1 0 7 APA ROT 00521414 100 1 0 9 APA APA 01142124 100 1 0 6 APA CODE 00121212 150 1 0 8 APA SERV 00011145 600 1 0 

Очевидно, я оставил несколько столбцов, не имеющих значения для моего вопроса. Когда я запрашиваю эту таблицу, я буду сортировать по одному из нескольких разных столбцов (пользовательский интерфейс позволяет отдельным пользователям изменять колонку сортировки и порядок), и у меня может быть предложение поиска, в этом случае я сделаю предложение LIKE на NAME и DIN.

Я хочу знать, учитывая информацию о сортировке и информацию о поиске, а также идентификатор определенного продукта (скажем, я искал 004, который возвратил 3 результата, и я просматриваю один из них), как я мог получить следующий и предыдущие продукты?

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

  • magento ограничение количества возвращенных предметов в вызове коллекции продуктов
  • Проблема с разбиением на страницы в пользовательском шаблоне WordPress
  • Как реализовать разбиение на страницы на пользовательский WP_Query Ajax
  • Код разбивки на PHP
  • Ссылка на текущую ссылку с разбивкой по страницам не выделяется

Есть ли хороший и эффективный способ сделать это в SQL, или мне лучше использовать PHP? Любые идеи также приветствуются.

В настоящее время используется этот SQL-запрос, который испытывает проблемы, если я сортирую по столбцу strength как есть повторяющиеся значения

 SELECT T.* FROM `wp_products` T INNER JOIN `wp_products` curr on curr.id = 38 AND ((T.strength = curr.strength and T.id < curr.id) OR (T.strength > curr.strength)) WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE '%%' OR T.din LIKE '%%') ORDER BY T.strength ASC, T.id ASC LIMIT 1 

Мой PHP-код (с использованием WordPress) (разработан для получения следующего элемента)

  $sql = 'SELECT T.* FROM `' . $wpdb->prefix . 'apsi_products` T INNER JOIN `' . $wpdb->prefix . 'apsi_products` curr on curr.id = ' . $item->id . ' AND ((T.' . $wpdb->escape( $query['orderby'] ) . ' = curr.' . $wpdb->escape( $query['orderby'] ) . ' and T.id > curr.id) OR (T.' . $wpdb->escape( $query['orderby'] ) . ' > curr.' . $wpdb->escape( $query['orderby'] ) . ')) WHERE T.active = 1 AND T.deleted = 0 AND (T.name LIKE '%' . $query['where'] . '%' OR T.din LIKE '%' . $query['where'] . '%') ORDER BY T.' . $wpdb->escape( $query['orderby'] ) . ' ' . $query['order'] . ', T.id ASC LIMIT 1;'; 
  • Zend_Paginator возвращает объекты
  • Атрибут Ajax для API Instagram пытался исправить ошибку
  • Как получить общее количество столбцов, если строки разбиты на страницы?
  • Разбиение страниц на PHP и MySQL?
  • Как рассчитать смещения для разбивки на страницы?

Вам нужно иметь ссылку на текущую запись, а затем постепенно искать следующую запись на основе отсортированных столбцов. В приведенном ниже примере предполагается, что он отсортирован по

 ORDER BY Active, DIN, NAME 

Первый:

 SELECT * FROM TABLE WHERE NAME LIKE '%X%' AND DIN LIKE '%%' ORDER BY Active, DIN, Name LIMIT 1; 

Далее: ( убедитесь, что вы отделили CURR.ID = 6 и AND-OR с соответствующими скобками! )

 SELECT * FROM TABLE T INNER JOIN TABLE CURR ON CURR.ID = 6 # the current ID being viewed AND ((T.Active = Curr.Active AND T.DIN = Curr.DIN AND T.NAME > Curr.Name) OR (T.Active = Curr.Active AND T.DIN > Curr.DIN) OR T.Active > Curr.Active) WHERE T.NAME LIKE '%X%' AND T.DIN LIKE '%%' ORDER BY T.Active, T.DIN, T.Name LIMIT 1; 

Рабочий образец, представленный ниже

 create table products (ID int, SEED int, NAME varchar(20), DIN varchar(10), ACTIVE int, DELETED int); insert products values (1, 0, 'Product #1', '004812', 1, 0), (2, 0, 'Product #2', '004942', 0, 0), (3, 0, 'Product #3', '004966', 1, 0), (4, 0, 'Product #4', '007437', 1, 1), (5, 2, 'Product #2', '004944', 0, 0), (6, 2, 'Product #2', '004944', 1, 0); SELECT * FROM products WHERE active = 1 AND deleted = 0 ORDER BY din DESC, ID desc; Output: "ID";"SEED";"NAME";"DIN";"ACTIVE";"DELETED" "3";"0";"Product #3";"004966";"1";"0" "6";"2";"Product #2";"004944";"1";"0" "1";"0";"Product #1";"004812";"1";"0" 

Если текущий – это строка с ID = 6, следующая запись может быть получена с использованием

 SELECT T.* FROM products T INNER JOIN products curr on curr.ID = 6 AND ((T.din = curr.din and T.ID > curr.ID) OR (T.din < curr.din)) WHERE T.active = 1 AND T.deleted = 0 ORDER BY T.din DESC, T.ID ASC LIMIT 1; 

Без уровня кеша персистентности, такого как memcached , где вы можете хранить результаты и получать его без повторной выдачи запроса, простым решением может быть включение кеша запросов в mysql. Таким образом, если кеш не является недействительным из других запросов, при повторной выдаче запроса стоимость вытягивания результата будет снижена

Для каждого отображаемого результата установите следующую и предыдущую ссылки с соответствующими идентификаторами.

Порядок сортировки не может быть изменен из представления деталей.

Интересный вопрос. Я не думаю, что вы можете сделать это в одном запросе, но вы можете снять его, возможно, тремя.

Первый запрос вызывает строку ответа. Хитрость заключалась бы в том, чтобы удержать значение для столбца, который они отсортировали. Предположим, что это «SortedColumn», а значение «M». Предположим, что идентификатор строки у вас был 10.

Второй запрос будет таким же, как и первый, но будет «топ-1» и добавит в предложение where «… и sortedColumn> =« M »и id <> 10« Это приведет к следующей строке. Возможно, вы захотите вернуть 10 строк и удерживать их, чтобы это не повторялось снова и снова.

Чтобы получить предыдущее, переключите свое упорядочение на нисходящее, а добавленное предложение where – «… и sortColumn <= ‘M’ и id <> 10″. Это дает вам предыдущую строку. Опять же, 10 строк могут быть более полезными для вашего пользователя.

Надеюсь это поможет.

Я хотел бы использовать один SQL-запрос (в MySQL), чтобы найти запись, которая приходит после той, которую я указываю.

I.e., если таблица имеет:

id, fruit
--  -----
1   apples
2   pears
3   oranges

Я хотел бы сделать запрос типа:

SELECT * FROM table where previous_record has id=1 order by id;

(ясно, что не настоящий синтаксис SQL, я просто использую псевдо-SQL, чтобы проиллюстрировать, чего я пытаюсь достичь)

который вернется:

2, pears

Мое текущее решение – это просто взять все записи и просмотреть их на PHP, но это медленнее, чем хотелось бы. Есть ли более быстрый способ сделать это?

Я был бы доволен тем, что возвратило две строки – то есть с указанным значением и следующей строкой.

EDIT: Извините, мой вопрос был плохо сформулирован. К сожалению, мое определение “следующий” не основано на ID, а на алфавитном порядке имени фруктов. Следовательно, мой пример выше неверен и должен возвращать апельсины, поскольку он идет в алфавитном порядке после яблок. Есть ли способ выполнить сравнение строк, а не идентификаторов?

Добавить комментарий