Scott Klarr Jr
How to select previous/next rows in MySql
I decided to add the previous post & next post navigational links that you see at the top of this page for more internal cross-links as well as an easier means to browse posts. I went to type up the code really quick and had a temporary "coding block." So naturally I check google for a quick answer and found a few results of people asking for the same thing but no posted solution that I could see.
After thinking about it, i came up with 2 solutions that aren't very good, and then finally the "correct" answer - which of course ended up being extremely simple. I will first go over the two methods that are NOT the most ideal way to do it. Hopefully this will help somebody looking for the same solution.
Bad Idea #1
My first thought was to simply run a query like this:
SELECT
id, title
FROM
topics
WHERE
id=($currentTopicId + 1)
LIMIT 1
The problem is that in most real-world databases, including my blog, information isn't permanent. Sometimes things need to be deleted/edited/hidden/etc for whatever reason. Lets say the current topic's ID is 37 and you want to display a link to the following post, however there is no longer a topic with ID 38 because you deleted it. This would cause the above query to return nothing. The solution, if you can call it that, to this dilemma would be to setup a loop or recursive function to keep querying incremental IDs until a result is found. That, however, is a bad idea because it is a waste of resources to continually query the database like that when there is a better way to do it, which will be explained in a minute.
Bad Idea #2
The second idea was to pull a list of all the IDs from the database, use a loop to figure out the ID numbers before and after the current ID, and then pull those two rows from the database. Just as above, this would work ok, but wastes resources that become very valuable in larger scale applications.
The Best Way
Once this solution came to me I was kind of embarrassed that I actually had to think about it. Here is the MySQL query to get the next row:
SELECT id, title
FROM topics
WHERE id > $currentTopicId
ORDER BY id ASC
LIMIT 1
And for the previous record
SELECT id, title
FROM topics
WHERE id < $currentTopicId
ORDER BY id DESC
LIMIT 1
For a quick explanation of the first query: we are telling mysql to look for any rows in which the ID is larger than the current ID. It takes those results and orders them by the id in an ascending order (smallest to largest) and finally limits the result to the first of the list. So regardless of the difference in ID numbers, these two queries will allow you to get the next or previous available row. This of course is dependent on your table having auto-incremented IDs, which it probably should.
You can also add other statements to the where clause, for example this is the actual query I used in order to only count the topics I have set to visible:
SELECT id, title
FROM topics
WHERE
id > $currentTopicId and
visible=1
ORDER BY id ASC
LIMIT 1



Paolo May 08, 2008
Genius.
chris Jul 28, 2010
he he :) exactly how I just did it... but then I was still thinking... can I make this query into one?
(being a long query with 4 joins and 4 subqueries... huge database...)
So far... not worth bothering :D
Aren May 29, 2008
it works only when ordered by id. Try order by ORDER BY title and it will fall apart
michel Jul 01, 2008
Hello, How to get the previous row of the current row,
example.. previews row name = Image
current name = Imagetek
how to go back to the Image row
Patrick Jul 25, 2008
Thats all fine as long as the ID is sequential, but if you are filtering or sorting differnt columns the id sequence will change so the the next rec up might have a id of a lower value.
Pierre Dec 11, 2008
If you need to use another field than id to sort your rows, then you'll need a sub request. For example if you use the date to order your rows :
SELECT id,title
FROM topics
WHERE date > (SELECT date FROM topics WHERE id=$currentTopicId)
AND visible=1
ORDER BY date ASC
LIMIT 1
Frog Dec 31, 2008
good post, duh! I feel so stupid now. :)
Kunal Mehta Jan 14, 2009
Very nice blog. I appreciate your efforts.
Can you please let me is it possible with one query?
Kunal Mehta
---
http://elevatesoftsolutions.in/post/2009/01/11/how-portal-iframes-open-splendid-crm-page-like-sugar-crm-php.aspx
academo Feb 14, 2009
hey men, thank you, i really think the first bad idea, and you solution is to simple and rigth :)
krinksy Mar 05, 2009
How would I go about doing this if I were to order by a text string? Because obviously the id before the current row could actually be greater than the current id and vice versa. Is it possible to do it for a query that is ordering independant of an id or date, i.e. somthing that can't have '>' or '
Vernon May 22, 2009
Thanks Scott,
I have been stuck with this idea and also found it rather hard to find a good solution by Googling for it...until I found your solution, of course.
Andie Jun 03, 2009
Well it works great for 'next' but for 'previous' it returns the very first row it finds in the query - which in each case will be the same. So if the current id is say 343 / 345 / 350 it keeps returning 340 when I run id < $currentTopicId
Andie Jun 03, 2009
I stand corrected, it was my code that had a problem. Thanks for a great idea :)
Mark Aug 18, 2009
Great tip! One question...
How can I make a function that will make the query loop back to the highest id when the next query is executed on the oldest inserted ID? Essentially I'd like to make a loop back to the newest. A class is needed, perhaps?
Scott Klarr Aug 18, 2009
I am not sure about doing it directly in the query, but it is easy enough to do in php (or whatever language you are using). After the "next row" query is ran, check to see if the returned result is empty. If it is, you know you are at the end of the line and then you can simply do another query that selects the first row (SELECT id, title FROM topics ORDER BY id ASC LIMIT 1).
Mark Aug 19, 2009
Thanks Scott!
Another piece of basic logic I puzzled over! I'm a bit embarrassed I didn't arrive at that immediately.
Rasmus Oct 15, 2009
So logic, and i thought about it for so long time :-)
Gordon Nov 06, 2009
Excellent. Thanks.
Joe Joe Dancer Dec 03, 2009
I did find other solutions posted online, but they were all convoluted and complicated. Your solution is so simple - and it works beautifully! Thank you.
Adnan Mar 02, 2010
Really nice idea, looked all over the forums for it and couldn't find it
Thank you very much, you've made my day
keno974 Mar 11, 2010
Thx a lot for your script, it's work fine, i have just change ASC by DESC order for my id on the previous sql instruction
GG !!!!
abdullah Apr 05, 2010
çok teşekkürler (very thanks)...
John K Apr 11, 2010
Thats a really great idea! Awesome post, I'm embarrassed I didn't think of it either!
Yury G. May 08, 2010
Man, that's just amazing how easy some complicated at the first glance things can go when you start using simple logic! If you need a greater id selected you just go on and use a greater sign in the where clause =)
Sql is the most logical language indeed. Thanks!
John Komla May 21, 2010
This is Genius broda !
Nick Jun 05, 2010
Fantastic work! Thanks for your help buddy :)
Djordje Aug 07, 2010
You can do it in a single query by using UNION or OR in conditions. You then get 2 results, then melodramatically determine which one is which.
Prasad Aug 21, 2010
Thanks for posting this. I just did something similar to your first bad idea and realized that if I want to disable a page using the a page_disabled column, the code would not work. Your idea works perfectly for what I need. Thanks again!