Я не понял смысла числа в points, но полагаю что оно просто рандомное)
В таком случае, представляестся такое:
select id, points, row_number() over (order by points) from users;
Эта команда отсортирует всех пользователей по points по возрастанию, и добавит им последовательный номер так, что у юзера с row_number = 1 будет наименьший points, а у максимального row_number - наибольший.
Благодаря последовательному ключу мы можем легко по циклу составить пары:
for i in range ({число юзеров}/2)
USER (row_number = i) <-> USER (row_number = 100 - i)
Где собирать команду вместе - уже решать вам)
Но я считаю лучше всего для этих целей написать в postgres функцию, например, на pl/PgSQL.
Функция может пройтись по циклу и на лету сгенерировать таблицу с командными парами.
https://postgrespro.ru/docs/postgresql/11/plpgsql-...