简体   繁体   中英

Find previous/next records when given alphabetic order in sql?

I have a table people

id    name
----+-----
54    Tango
76    Alpha
95    Radio

When displaying the records on the web those names are ordered alphabetically

Alpha, Radio, Tango

Lets say we're viewing Radio details and want to navigate to the next (Tango) or prevoius (Alpha) record using some links.

How can I find those id's to create the needed links?

Finding next superior or inferior id won't work.

Is this possible?

Thanks.

You can do this:

SELECT name
FROM
(
   SELECT name, (@rownum := @rownum + 1) rank
   FROM people, (SELECT @rownum := 0) t
   ORDER BY name
) t WHERE rank = @n

You should use the new ranking number column rank to create those links. Then you should control the value of the parameter @n to get the previous or the next.

SQL Fiddle Demo

it is not done so yet.

prev

SELECT Id FROM people WHERE name < 'Radio' ORDER BY name DESC LIMIT 1

next

SELECT Id FROM people WHERE name > 'Radio' ORDER BY name ASC LIMIT 1

You can select the previous name with max().

select max(name) as name
from people
where name < 'Radio';

Then you can use that query as a derived table in a JOIN.

select id
from people
inner join 
  (select max(name) as name
   from people
   where name < 'Radio') as t2 on t2.name = people.name

Next name is similar, using min() and the > operator.

If your design allows duplicate names, the derived table will return multiple rows. That's a problem generally for artificial keys.

What does next mean when you start with {100, 'Obama'}, and your data includes

{ 50, 'Romney'}
{150, 'Romney'}
{843, 'Romney'}

If names can repeat, how do you identify the row that is "current" when you want to find the previous and next row? I assume you identify it by id. In any case, you need to have some way to address rows uniquely.

I tested this:

USE test;
DROP TABLE IF EXISTS t;
CREATE TABLE t (id INT PRIMARY KEY, name VARCHAR(10));

INSERT INTO t (id, name) VALUES
(54, 'Tango'),
(76, 'Alpha'),
(78, 'Alpha'),
(95, 'Radio');

(SELECT * FROM t WHERE id >= 76 ORDER BY id ASC LIMIT 2)
UNION
(SELECT * FROM t WHERE id <= 76 ORDER BY id DESC LIMIT 2)
ORDER BY id ASC;

UNION takes care of eliminating the duplicate row where id=76

Here's the result:

+----+-------+
| id | name  |
+----+-------+
| 54 | Tango |
| 76 | Alpha |
| 78 | Alpha |
+----+-------+

Here is the cleanest and most efficient way: To get next:

 select min(name) people where name > 'RADIO';

To get previous:

 select max(name) people where name < 'RADIO';

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM