Hi,

Let say I have a table containing 100 student records:

CREATE TABLE students (
  id SERIAL,
  name TEXT NOT NULL,
  CONSTRAINT students_pk PRIMARY KEY (id)
);

It is easy to query for "next page" with keyset pagination. For example, if I want to get 10 rows of student records after reading student records #10 to #20:

SELECT id, name
FROM students
WHERE id > 20
ORDER BY id ASC
LIMIT 10;

But how to query for "previous page"? Let say I'm reading student records #20 to #30, now I want to get 10 student records before the current set. Here is how I would do it:

SELECT id, name
FROM (
  SELECT id, name
  FROM students
  WHERE id < 20
  ORDER BY id DESC
  LIMIT 10
) AS t
ORDER BY id ASC;

In the sub-query, I sort the student records by the student ID in descending order, then I get 10 rows of student record, and finally sort those 10 student records by student ID in ascending order.

Is it a good way to do it? Is there any way to avoid doing the sorting twice?

Many thanks.

asked Aug 17 '14 at 19:42

alextsg's gravatar image

alextsg
16113


One Answer:

Hi!

The way you do it is the way it is to be done. However, one clarifications:

Is there any way to avoid doing the sorting twice?

Although you have two order by clauses, the database must not necessarily do two sort operations. If you provide the right index for the inner query, only the outer order by needs to be done. And that is only for 10 rows, not a big potential for performance issues.

CREATE INDEX tmp ON students (id);

You already have this index in that example to maintain the PK, I'm mentioning it nevertheless because real-world cases often require another index.

answered Aug 21 '14 at 09:49

Markus%20Winand's gravatar image

Markus Winand ♦♦
93651120

Thank you.

(Aug 22 '14 at 04:21) alextsg