Чтобы узнать все имена, которые есть у наших пользователей, нужно выполнить запрос не всех полей, а только имени:
-- Получить список имен всех пользователей
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
. С ее помощью вы можете узнать все необходимые значения, найти уникальные записи среди них и избавиться от дублей.
Дополнительные материалы
Остались вопросы? Задайте их в разделе «Обсуждение»
Вам ответят команда поддержки Хекслета или другие студенты