У меня есть таблица со столбцом временной метки, примерно так:
╔═══════╦════════════╦
║ name ║ date_time ║
╠═══════╬════════════╬
║ A ║ 100 ║
║ B ║ 110 ║
║ C ║ 120 ║
║ D ║ 140 ║
║ E ║ 180 ║
║ F ║ 190 ║
╚═══════╩════════════╩
Мне нужно вернуть записи, чтобы записи попали в две группы: записи, в которых date_time находится в будущем, являются первой группой, а записи, где date_time находится в прошлом, - второй группой. Записи в будущем необходимо отсортировать в порядке возрастания (т. Е. Ближайшие к настоящему времени идут первыми), а записи в прошлом необходимо отсортировать в порядке убывания.
Мне удалось решить эту проблему, выполнив два отдельных запроса и объединив результаты с помощью union all, но это не очень эффективно, и мне было любопытно узнать, есть ли лучший подход? Может быть, используя условную сортировку по порядку?


В Postgres вы можете сортировать логические значения - значения false идут перед значениями true. Таким образом, вы можете сортировать по двум выражениям - условию, которое проверяет, находится ли запись в прошлом или будущем, и абсолютному расстоянию между ней и текущей временной меткой:
SELECT *
FROM mytable
ORDER BY date_time < CURRENT_TIMESTAMP,
ABS(EXTRACT(EPOCH FROM CURRENT_TIMESTAMP) -
EXTRACT(EPOCH FROM date_time))
Мне нравится это решение. Это довольно просто и по делу. Голосование за.
@TheImpaler current_timestamp - это функция stable, поэтому CTE не нужен. См. postgresql.org/docs/10/static/xfunc-volatility.html
Чувак, ты узнаешь что-то новое каждый день: D Не знал о стабильности всех функций даты / времени в PostgreSQL (которые используют время начала транзакции). Спасибо за разъяснения.
Я бы сделал это с помощью трех ключей сортировки:
order by (date_time < current_timestamp),
(case when date_time < current_timestamp then date_time end) desc,
date_time asc;
Здесь - это рекстестер.
Используйте и
ORDER BYс предложениемCASEв нем.