Skip to main content
2 of 4
clarify
Erwin Brandstetter
  • 182.1k
  • 28
  • 457
  • 620

Get your case straight. First, a proper table definition. We need a PK or similar to break ties unambiguously:

CREATE TABLE users (
  user_id     int PRIMARY KEY
, update_time timestamptz NOT NULL
, about_me    text NOT NULL
);

The column update_time is type timestamptz. Keep working with timestamptz, and don't mix with timestamp.

Next, sample rows to exhibit possible problems:

INSERT INTO users VALUES
  (1, '2023-04-06 19:59:56.771388 +00:00', 'Hello! How are you?')
, (3, '2023-04-02 03:31:09.833925 +00:00', 'Hello!!!')
, (2, '2023-04-06 00:36:26.822102 +00:00', 'Hello!')
, (4, '2023-04-05 19:16:20.968274 +00:00', 'Hey!')
, (5, '2023-04-02 03:31:09.833925 +00:00', 'Same len')
, (7, '2023-05-02 03:31:09.833925 +00:00', 'Later!!!')
, (6, '2023-03-02 03:31:09.833925 +00:00', 'Earlier!')
;

Proper base query:

SELECT user_id, update_time, about_me
FROM   users u
ORDER  BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC
        , length(about_me) DESC
        , user_id DESC;  -- !

'2023-04-07 23:11:56+0' being your arbitrary (but constant!) time anchor.

Notably, you added user_id as 3rd expression to ORDER BY to break ties. That's good. But if you want to keep using Row Constructor Comparison, all 3 expressions must share the same sort direction. All ASCENDING or all DESCENDING. Else it gets more complex and expensive.
Also, add user_id to the SELECT list. It's essential for your pagination.

Then, to get the 1st page with an example page size of 3:

SELECT user_id, update_time, about_me
FROM   users u
ORDER  BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC
     , length(about_me) DESC
     , user_id DESC
LIMIT  3;

2nd page:

SELECT user_id, update_time, about_me
FROM   users u
WHERE (date_bin('14 days', update_time, '2023-04-07 23:11:56+0'), length(about_me), user_id)
    < ('2023-03-25 00:11:56+01', 8, 5)
ORDER  BY date_bin('14 days', update_time, '2023-04-07 23:11:56+0') DESC
     , length(about_me) DESC
     , user_id DESC
LIMIT  3;

('2023-03-25 00:11:56+01', 8, 5) being derived from the last row of the first page.
'2023-03-25 00:11:56+01' is the result of the date_bin() expression. You might add it to the SELECT list for simplicity.

fiddle

Erwin Brandstetter
  • 182.1k
  • 28
  • 457
  • 620