Зарегистрируйтесь, чтобы продолжить обучение

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 позволяет отдельно указывать два типа полей — для проверки уникальности и для результирующей выборки:

-- Все записи, уникальные по 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 — указан в сортировке первым. В противном случае результат будет неверным.

В таких запросах сначала выполняется сортировка и уже после этого отрабатывает DISTINCT, так как он берет первую запись из группы. Но мы ведь не знаем какая запись первая. Нужно гарантировать порядок, в чем помогает ORDER BY.

Выводы

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


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

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

Аватары экспертов Хекслета

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

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

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

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

  • 130 курсов, 2000+ часов теории
  • 1000 практических заданий в браузере
  • 360 000 студентов
Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»

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

Логотип компании Альфа Банк
Логотип компании Aviasales
Логотип компании Yandex
Логотип компании Tinkoff

Используйте Хекслет по-максимуму!

  • Задавайте вопросы по уроку
  • Проверяйте знания в квизах
  • Проходите практику прямо в браузере
  • Отслеживайте свой прогресс

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

Отправляя форму, вы принимаете «Соглашение об обработке персональных данных» и условия «Оферты», а также соглашаетесь с «Условиями использования»