Пошук уроків, статей та іншого контенту
Приберете дублікати з результатів запиту та навчитеся отримувати унікальні значення одного або кількох стовпців.
DISTINCTОператор DISTINCT прибирає дублікати з результату запиту SELECT.
Без DISTINCT запит повертає всі рядки, які відповідають умові. Якщо однакове значення зустрічається кілька разів, воно також буде виведене кілька разів.
SELECT DISTINCT column_name
FROM table_name;DISTINCT застосовується до всіх стовпців, зазначених у SELECT.
Уявімо таблицю замовлень:
WITH orders(order_id, customer_id, status) AS (
VALUES
(1, 101, 'paid'),
(2, 102, 'new'),
(3, 101, 'paid'),
(4, 103, 'shipped'),
(5, 102, 'new')
)
SELECT customer_id
FROM orders;Результат:
customer_id
-------------
101
102
101
103
102Ідентифікатори клієнтів повторюються, тому що один клієнт може мати кілька замовлень.
Щоб отримати кожного клієнта лише один раз, використаємо DISTINCT:
WITH orders(order_id, customer_id, status) AS (
VALUES
(1, 101, 'paid'),
(2, 102, 'new'),
(3, 101, 'paid'),
(4, 103, 'shipped'),
(5, 102, 'new')
)
SELECT DISTINCT customer_id
FROM orders;Результат:
customer_id
-------------
101
102
103Порядок рядків без ORDER BY не гарантований. Якщо потрібен певний порядок, додайте сортування:
WITH orders(order_id, customer_id, status) AS (
VALUES
(1, 101, 'paid'),
(2, 102, 'new'),
(3, 101, 'paid'),
(4, 103, 'shipped'),
(5, 102, 'new')
)
SELECT DISTINCT customer_id
FROM orders
ORDER BY customer_id;Якщо вибрати кілька стовпців, DISTINCT перевіряє унікальність усієї комбінації значень.
WITH orders(order_id, customer_id, status) AS (
VALUES
(1, 101, 'paid'),
(2, 102, 'new'),
(3, 101, 'paid'),
(4, 103, 'shipped'),
(5, 102, 'new'),
(6, 101, 'new')
)
SELECT DISTINCT customer_id, status
FROM orders
ORDER BY customer_id, status;Результат:
customer_id | status
-------------+---------
101 | new
101 | paid
102 | new
103 | shippedРядки з однаковими customer_id і status об'єднуються в один результат.
Важливо: DISTINCT не означає «унікальні значення кожного стовпця окремо». Він залишає унікальні пари:
customer_id = 101, status = 'paid';
customer_id = 101, status = 'new'.
Це дві різні комбінації, тому обидві залишаються в результаті.
DISTINCT і значення NULLDISTINCT вважає всі значення NULL одним унікальним значенням.
WITH users(user_id, city) AS (
VALUES
(1, 'Kyiv'),
(2, NULL),
(3, 'Lviv'),
(4, NULL)
)
SELECT DISTINCT city
FROM users;Результат міститиме:
city
------
Kyiv
Lviv
NULLДва рядки з NULL перетворюються на один рядок у результаті.
DISTINCT разом із ORDER BYРезультат із дублікатами можна одночасно прибрати та відсортувати:
WITH products(product_id, category) AS (
VALUES
(1, 'Books'),
(2, 'Games'),
(3, 'Books'),
(4, 'Music')
)
SELECT DISTINCT category
FROM products
ORDER BY category;Якщо використовується SELECT DISTINCT, вираз для сортування зазвичай має бути присутнім і в списку SELECT.
Правильно:
SELECT DISTINCT category
FROM products
ORDER BY category;Потенційно проблемний варіант:
SELECT DISTINCT category
FROM products
ORDER BY product_id;У результаті вибирається лише category, але сортування виконується за product_id. PostgreSQL може повідомити про помилку, оскільки для однакового category немає однозначного product_id.
Загальна форма запиту:
SELECT DISTINCT column_1, column_2
FROM table_name
WHERE condition
ORDER BY column_1;WHERE застосовується до того, як PostgreSQL прибирає дублікати:
WITH orders(order_id, customer_id, status) AS (
VALUES
(1, 101, 'paid'),
(2, 101, 'new'),
(3, 102, 'paid'),
(4, 103, 'cancelled'),
(5, 103, 'paid')
)
SELECT DISTINCT customer_id
FROM orders
WHERE status = 'paid'
ORDER BY customer_id;Спочатку залишаються лише оплачені замовлення, а потім із них вибираються унікальні клієнти:
customer_id
-------------
101
102
103DISTINCT у виразахDISTINCT може застосовуватися не лише до назв стовпців, а й до виразів.
WITH users(user_id, email) AS (
VALUES
(1, 'Alice@Example.com'),
(2, 'alice@example.com'),
(3, 'bob@example.com')
)
SELECT DISTINCT LOWER(email) AS normalized_email
FROM users
ORDER BY normalized_email;Функція LOWER переводить електронні адреси в нижній регістр. Після цього два перші значення стають однаковими, тому в результаті залишиться лише одна адреса alice@example.com.
DISTINCT відрізняється від DISTINCT ONУ PostgreSQL існує окремий синтаксис DISTINCT ON, але це інший інструмент.
DISTINCT залишає унікальні комбінації вибраних стовпців.
DISTINCT ON залишає один рядок із кожної групи та потребує правильного ORDER BY.
Для простого отримання унікальних значень використовуйте звичайний DISTINCT.
DISTINCTЯкщо потрібно отримати список унікальних категорій, такого запиту недостатньо:
SELECT category
FROM products;Він може повернути одну категорію кілька разів. Потрібно написати:
SELECT DISTINCT category
FROM products;Запит:
SELECT DISTINCT customer_id, status
FROM orders;повертає унікальні комбінації customer_id і status, а не окремий список унікальних клієнтів та окремий список унікальних статусів.
Якщо потрібні лише клієнти:
SELECT DISTINCT customer_id
FROM orders;Якщо потрібні лише статуси:
SELECT DISTINCT status
FROM orders;DISTINCT для приховування помилки в JOINDISTINCT іноді використовують, щоб прибрати дублікати, які з'явилися через неправильну умову JOIN. Це може приховати проблему в запиті.
Спочатку перевірте, чому рядки дублюються, і лише потім додавайте DISTINCT, якщо повтори справді не потрібні за змістом.
DISTINCT не сортує результат автоматично. Для гарантованого порядку використовуйте ORDER BY:
SELECT DISTINCT category
FROM products
ORDER BY category;DISTINCT прибирає дублікати з результату SELECT.
Для одного стовпця він повертає унікальні значення цього стовпця.
Для кількох стовпців він повертає унікальні комбінації їхніх значень.
Усі NULL у межах вибраних стовпців вважаються одним унікальним значенням.
WHERE фільтрує рядки до застосування DISTINCT.
DISTINCT не сортує результат, тому для порядку потрібен ORDER BY.