SELECT DISTINCT ON: недооценённая возможность PostgreSQL
SELECT DISTINCT ON: недооценённая возможность PostgreSQL В арсенале PostgreSQL есть множество синтаксических конструкций, которые разработчики знают «в лицо», но редко используют по-настоящему. Одна из них — SELECT DISTINCT ON. Большинство из нас привыкли к классическому DISTINCT: он убирает полные дубликаты строк. А вот расширение DISTINCT ON используется сильно реже. И напрасно! DISTINCT ON позволяет оставить только первую строку из каждой группы записей, сгруппированных по указанному полю (или набору полей). При этом возвращается целая строка, а не агрегированное значение, как в GROUP BY. Классический пример — для каждого клиента получить его самый последний заказ. Без DISTINCT ON пришлось бы использовать оконную функцию или самосоединение. С ним — запрос лаконичен и легко читаем: SELECT DISTINCT ON (customer_id) id, customer_id, total_amount, created_at FROM orders ORDER BY customer_id, created_at DESC; Что здесь происходит: DISTINCT ON (customer_id) — говорит СУБД оставить по одной строке на каждого уникального клиента. ORDER BY определяет, какая именно строка из группы будет выбрана. В примере — самая поздняя (по убыванию created_at). Важное ограничение, о котором часто забывают: первый столбец (или несколько) в ORDER BY обязан совпадать с полями, указанными в DISTINCT ON. Иначе PostgreSQL не сможет однозначно определить порядок внутри группы, и результат может оказаться недетерминированным. Это не ошибка проектирования, а строгое требование логики: СУБД должна знать, по какому критерию выбирать «первую» строку. Если в Ваших запросах встречаются задачи типа «самый последний», «самый ранний» или «на максимальную сумму» в разрезе некоторого объекта — присмотритесь к DISTINCT ON. Вы удивитесь, как часто он оказывается именно тем, что нужно, и как редко о нём вспоминают. Попробуйте в следующий раз — и, возможно, он займёт почётное место в вашем SQL-арсенале. 🐘