Основы реляционных баз данных

DISTINCT

DISTINCT

Предположим, что нам нужно узнать все имена, которые есть у наших пользователей. Самый простой способ сделать это — выполнить запрос не всех полей, а только имени:

-- получить список имён всех пользователей
SELECT first_name FROM users;

Но проблема в том, что эти имена наверняка дублируются: ведь разные люди вполне могут иметь одинаковые имена. Избавиться от дублей можно с помощью DISTINCT.

SELECT DISTINCT first_name FROM users;

 first_name
------------
 Delphine
 Hanna
 Maxwell
 Russell
 Mia

Такой запрос выведет только уникальные имена.

DISTINCT позволяет указывать не одно, а сразу несколько полей:

-- DISTINCT добавляется в запрос только один раз, независимо от того, сколько колонок перечисляется
SELECT DISTINCT first_name, last_name FROM users;

 first_name |   last_name
------------+---------------
 Rhiannon   | Tremblay
 Vesta      | Kassulke
 Ena        | Gorczany
 Florencio  | Collier
 Garrett    | Koss

В эту выборку попадут все значения с уникальным сочетанием имён и фамилий. Это значит, что имена и фамилии повторяться могут, но пара всегда уникальна. Если в DISTINCT добавить первичный ключ (SELECT DISTINCT id, first_name FROM users), то запрос извлечёт все записи. Такой результат является следствием уникальности первичного ключа.

DISTINCT можно совмещать с агрегатными функциями (им посвящён отдельный урок): например, посчитать количество пользователей с уникальными именами:

SELECT COUNT(DISTINCT first_name) FROM users;

DISTINCT ON

Эта форма DISTINCT ON настолько сильно отличается от своей исходной формы, что о ней стоит сказать подробнее. В отличие от базовой формы, DISTINCT ON позволяет отдельно указывать поля, по которым проверяется уникальность, и поля, которые должны оказаться в результирующей выборке.

-- Все записи, уникальные по user_id
SELECT DISTINCT ON (user_id) * FROM topics;

 id | user_id |              title              | body                  |       created_at
----|---------|---------------------------------|-----------------------|------------------------
  2 |       2 | molestiae voluptas velit        | Quod quasi molestiae. | 2019-06-02 23:42:30.688

-- Все title для уникальных user_id
SELECT DISTINCT ON (user_id) title FROM topics;

             title
-------------------------
 molestiae voluptas velit

SELECT DISTINCT user_id, title FROM topics;
-- Такой запрос вернет совершенно другие данные, он вернет все уникальные пары user_id-title
-- То есть здесь возможно повторение user_id в результирующей выборке

SELECT DISTINCT ON (user_id, title) user_id, title FROM topics;
-- Этот запрос равносилен тому, что был выше

При работе с DISTINCT ON важно правильно использовать сортировку.

SELECT DISTINCT ON (user_id) id, user_id, title, created_at
  FROM topics
  ORDER BY user_id, created_at;

 id | user_id |            title             |       created_at
----+---------+------------------------------+-------------------------
 48 |       1 | qui non velit                | 2018-12-05 21:49:52.631
  7 |       4 | delectus in nihil            | 2018-12-06 00:46:32.712
 26 |       6 | rerum rerum recusandae       | 2018-12-05 18:39:47.937
 34 |       7 | soluta non voluptas          | 2018-12-06 07:55:00.095

Такой запрос вернёт первый созданный топик для каждого пользователя. Запросы с DISTINCT ON требуют того, чтобы первыми полями в ORDER BY следовали те поля, которые идут после ON. Только тогда сортировка отработает так, как ожидается. В запросе выше это user_id, он указан в сортировке первым. В противном случае (ORDER BY created_at, user_id), результат будет неверен.


Дополнительные материалы

  1. Официальная документация

<span class="translation_missing" title="translation missing: ru.web.courses.lessons.mentors.mentor_avatars">Mentor Avatars</span>

Остались вопросы? Задайте их в разделе «Обсуждение»

Вам ответят команда поддержки Хекслета или другие студенты.

Ошибки, сложный материал, вопросы >
Нашли опечатку или неточность?

Выделите текст, нажмите ctrl + enter и отправьте его нам. В течение нескольких дней мы исправим ошибку или улучшим формулировку.

Что-то не получается или материал кажется сложным?

Загляните в раздел «Обсуждение»:

  • задайте вопрос. Вы быстрее справитесь с трудностями и прокачаете навык постановки правильных вопросов, что пригодится и в учёбе, и в работе программистом;
  • расскажите о своих впечатлениях. Если курс слишком сложный, подробный отзыв поможет нам сделать его лучше;
  • изучите вопросы других учеников и ответы на них. Это база знаний, которой можно и нужно пользоваться.
Об обучении на Хекслете

Для полного доступа к курсу нужна профессиональная подписка

Профессиональная подписка откроет полный доступ ко всем курсам, упражнениям и урокам Хекслета, проектам и пожизненный доступ к теории пройденных уроков. Подписку можно отменить в любой момент.

Получить доступ
115
курсов
892
упражнения
2241
час теории
3196
тестов

Открыть доступ

Курсы программирования для новичков и опытных разработчиков. Начните обучение бесплатно.

  • 115 курсов, 2000+ часов теории
  • 800 практических заданий в браузере
  • 250 000 студентов

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».

Наши выпускники работают в компаниях:

Логотип компании Альфа Банк
Логотип компании Rambler
Логотип компании Bookmate
Логотип компании Botmother

Есть вопрос или хотите участвовать в обсуждении?

Зарегистрируйтесь или войдите в свой аккаунт

Отправляя форму, вы соглашаетесь c «Политикой конфиденциальности» и «Условиями оказания услуг».