Добавить в корзинуПозвонить
Найти в Дзене

DISTINCT ON: Как выбирать нужное, не нумеруя лишнего

В SQL есть стандартный DISTINCT, который используется так: SELECT DISTINCT names FROM table. Это означает: «Дай мне все УНИКАЛЬНЫЕ имена из таблицы». Представим, что в коробке лежат джинсы, футболки и кепки. Запрос SELECT DISTINCT clothes выдаст по одному экземпляру от каждого вида: одни джинсы, одну футболку и одну кепку. Добавив описательные атрибуты, например, DISTINCT clothes, color мы получим уникальные комбинации вида и цвета.Теперь мы можем достать по одной футболке зеленого и желтого цвета, но нам может попасться хлопковая, кашемировая или шелковая. Если мы хотим достать по одной штуке каждого вида, цвета и материала, мы напишем DISTINCT clothes, color, material — в общем, перечислим всё, что должно входить в уникальный набор. Эту фишку можно продвинуть и использовать DISTINCT ON. Мы пишем: DISTINCT ON (clothes, color, material) и добавляем ORDER BY, например, по price. С помощью DISTINCT ON мы указываем, по каким столбцам определять уникальность, а сортировкой (в данном случа

В SQL есть стандартный DISTINCT, который используется так: SELECT DISTINCT names FROM table. Это означает: «Дай мне все УНИКАЛЬНЫЕ имена из таблицы».

Представим, что в коробке лежат джинсы, футболки и кепки. Запрос SELECT DISTINCT clothes выдаст по одному экземпляру от каждого вида: одни джинсы, одну футболку и одну кепку.

Добавив описательные атрибуты, например, DISTINCT clothes, color мы получим уникальные комбинации вида и цвета.Теперь мы можем достать по одной футболке зеленого и желтого цвета, но нам может попасться хлопковая, кашемировая или шелковая. Если мы хотим достать по одной штуке каждого вида, цвета и материала, мы напишем DISTINCT clothes, color, material — в общем, перечислим всё, что должно входить в уникальный набор.

Эту фишку можно продвинуть и использовать DISTINCT ON.

Мы пишем: DISTINCT ON (clothes, color, material) и добавляем ORDER BY, например, по price. С помощью DISTINCT ON мы указываем, по каким столбцам определять уникальность, а сортировкой (в данном случае по цене) просто забираем самую дорогую вещь в этой категории.

Это хорошая альтернатива оконной функции ROW_NUMBER(). Обычно мы нумеруем список, а потом берем строки, где rn = 1. В таком случае оконка проходит по всей таблице, нумерует каждую строку, а потом выбирает нужное. DISTINCT ON работает иначе: мы задаем набор, сортируем его и сразу берем первую строку из каждой группы. Это сильно ускоряет и оптимизирует процесс.

Пример из другой части гардероба — выбираем кроссовки в магазине:

Обычный DISTINCT — просим продавца: «Покажи мне бренды, какие есть у вас в наличии». Он приносит одну коробку Nike, одну Adidas и одну Jordan.

ROW_NUMBER() — это если бы мы заставили продавца вынести из подсобки ВООБЩЕ ВСЕ кроссовки Nike, расставить их по цене от дорогих к дешевым, наклеить на каждую коробку порядковый номер и только потом отдать вам ту, что под номером один.

DISTINCT ON — это когда мы говорим: «Из каждого бренда принеси мне только самую дорогую пару». Продавец сразу идет к полке, берет топовую модель и не тратит время на перекладывание всего склада.

Результат тот же, но действий в разы меньше.

Важный нюанс: работает DISTINCT ON только в PostgreSQL.

Связи:

📌 Кстати, напоминает те самые «стопки книг», про которые писал в заметке про LATERAL . Но есть отличия — об этом в других постах.