DISTINCT SQL. Введение
DISTINCT — ключевое слово SQL для выборки уникальных значений. distinct sql — способ убрать дубликаты строк, посчитать уникальные сущности и нормализовать результаты отчётов. В этой статье приведены 100 примеров применения DISTINCT от базовых выборок до сложных конструкций с JOIN, подзапросами, условными выражениями CASE и комбинациями с агрегатами (COUNT, SUM, AVG, MIN, MAX). Все примеры универсальны: используется стандартный синтаксис SQL без диалектных расширений.
Синтаксис
SELECT DISTINCT колонка1, колонка2
FROM таблица;
Типовая конструкция
SELECT
DISTINCT c.country, c.city
FROM
customers AS c
WHERE
c.is_active = 1
ORDER BY
c.country, c.city;
Базовые выборки уникальных значений
Уникальные города клиентов с SELECT и фильтром активности в WHERE:
SELECT
DISTINCT c.city
FROM
customers AS c
WHERE
c.is_active = 1
ORDER BY
c.city;Единый список категорий товаров через SELECT:
SELECT
DISTINCT p.category
FROM
products AS p
ORDER BY
p.category;Разные страны поставщиков с сортировкой через ORDER BY:
SELECT
DISTINCT s.country
FROM
suppliers AS s
ORDER BY
s.country;Перечень доступных валют счетов:
SELECT
DISTINCT a.currency
FROM
accounts AS a
ORDER BY
a.currency;Справочник должностей из таблицы сотрудников:
SELECT
DISTINCT e.job_title
FROM
employees AS e
ORDER BY
e.job_title;Список жанров фильмов для фильтра:
SELECT
DISTINCT f.genre
FROM
films AS f
ORDER BY
f.genre;Единый набор меток постов блога:
SELECT
DISTINCT t.tag
FROM
post_tags AS t
ORDER BY
t.tag;Коды регионов из адресов клиентов:
SELECT
DISTINCT a.region_code
FROM
addresses AS a
ORDER BY
a.region_code;Типы операций в журнале транзакций:
SELECT
DISTINCT tx.kind
FROM
transactions AS tx
ORDER BY
tx.kind;Список моделей устройств для витрины:
SELECT
DISTINCT d.model
FROM
devices AS d
ORDER BY
d.model;Набор учебных предметов из оценок студентов:
SELECT
DISTINCT r.subject
FROM
results AS r
ORDER BY
r.subject;Справочник складов по наименованию:
SELECT
DISTINCT w.name
FROM
warehouses AS w
ORDER BY
w.name;Фильтрация через WHERE перед выборкой уникальных
только активные товары:
SELECT
DISTINCT p.brand
FROM
products p
WHERE
p.is_active = 1
ORDER BY
p.brand;транзакции за 2024 год:
SELECT
DISTINCT tx.currency
FROM
transactions tx
WHERE
tx.tx_date >= DATE '2024-01-01' AND tx.tx_date < DATE '2025-01-01'
ORDER BY
tx.currency;Уникальные значения — студенты очной формы:
SELECT
DISTINCT s.city
FROM
students s
WHERE
s.form = 'FULLTIME'
ORDER BY
s.city;заказы со статусом PAID
SELECT
DISTINCT o.payment_method
FROM
orders o
WHERE
o.status = 'PAID'
ORDER BY
o.payment_method;комментарии без спама:
SELECT
DISTINCT c.author
FROM
comments c
WHERE
c.is_spam = 0
ORDER BY
c.author;устройства в работе:
SELECT
DISTINCT d.model
FROM
devices d
WHERE
d.state = 'OK'
ORDER BY
d.model;пациенты старше 18:
SELECT
DISTINCT pt.city
FROM
patients pt
WHERE
pt.age >= 18
ORDER BY
pt.city;рейсы международные:
SELECT
DISTINCT f.airline
FROM
flights f
WHERE
f.is_international = 1
ORDER BY
f.airline;магазины с витриной онлайн:
SELECT
DISTINCT st.city
FROM
stores st
WHERE
st.has_online = 1
ORDER BY
st.city;кандидаты с опытом более 3 лет:
SELECT
DISTINCT cand.primary_skill
FROM
candidates cand
WHERE
cand.years_exp > 3
ORDER BY
cand.primary_skill;Уникальные комбинации нескольких колонок
пара город‑страна клиентов:
SELECT
DISTINCT c.country, c.city
FROM
customers c
ORDER BY
c.country, c.city;категория‑бренд товаров:
SELECT
DISTINCT p.category, p.brand
FROM
products p
ORDER BY
p.category, p.brand;автор‑тема постов:
SELECT
DISTINCT p.author_id, p.topic
FROM
posts p
ORDER BY
p.author_id, p.topic;факультет‑курс:
SELECT
DISTINCT c.faculty_id, c.course_code
FROM
courses c
ORDER BY
c.faculty_id, c.course_code;склад‑товар:
SELECT
DISTINCT s.warehouse_id, s.product_id
FROM
stock s
ORDER BY
s.warehouse_id, s.product_id;аккаунт‑валюта:
SELECT
DISTINCT a.account_no, a.currency
FROM
accounts a
ORDER BY
a.account_no, a.currency;поставщик‑страна:
SELECT
DISTINCT s.name, s.country
FROM
suppliers s
ORDER BY
s.name, s.country;рейс‑дата:
SELECT
DISTINCT f.flight_no, f.flight_date
FROM
flights f
ORDER BY
f.flight_no, f.flight_date;курс‑семестр:
SELECT
DISTINCT sc.course_id, sc.semester
FROM
schedule sc
ORDER BY
sc.course_id, sc.semester;клиника‑услуга:
SELECT
DISTINCT s.clinic_id, s.service_code
FROM
services s
ORDER BY
s.clinic_id, s.service_code;Подсчёт уникальных значений через COUNT(DISTINCT …)
Сколько городов у каждого клиента — сочетание GROUP BY:
SELECT
c.customer_id,
COUNT(DISTINCT a.city) AS cities_cnt
FROM
customers AS c
INNER JOIN addresses AS a
ON a.customer_id = c.customer_id
GROUP BY
c.customer_id
ORDER BY
c.customer_id;Количество уникальных товаров в заказе:
SELECT
o.order_id,
COUNT(DISTINCT oi.product_id) AS unique_items
FROM
orders AS o
INNER JOIN order_items AS oi
ON oi.order_id = o.order_id
GROUP BY
o.order_id;Число авторов, комментировавших пост:
SELECT
p.post_id,
COUNT(DISTINCT c.author_id) AS commenters
FROM
posts AS p
LEFT JOIN comments AS c
ON c.post_id = p.post_id
GROUP BY
p.post_id;Уникальные категории, в которых продаётся бренд:
SELECT
p.brand,
COUNT(DISTINCT p.category) AS cat_cnt
FROM
products AS p
GROUP BY
p.brand;Количество уникальных пациентов врача:
SELECT
v.doctor_id,
COUNT(DISTINCT v.patient_id) AS unique_patients
FROM
visits AS v
GROUP BY
v.doctor_id;Сколько валют использовал клиент в платежах:
SELECT
p.customer_id,
COUNT(DISTINCT p.currency) AS used_currencies
FROM
payments AS p
GROUP BY
p.customer_id;Число стран, из которых приходили заказы:
SELECT
o.store_id,
COUNT(DISTINCT a.country) AS countries
FROM
orders AS o
INNER JOIN addresses AS a
ON a.address_id = o.shipping_address_id
GROUP BY
o.store_id;Количество уникальных устройств пользователя:
SELECT
l.user_id,
COUNT(DISTINCT l.device_id) AS devices
FROM
logins AS l
GROUP BY
l.user_id;Уникальные жанры, в которых снимался актёр:
SELECT
a.actor_id,
COUNT(DISTINCT f.genre) AS genres
FROM
actors AS a
INNER JOIN film_cast AS fc
ON fc.actor_id = a.actor_id
INNER JOIN films AS f
ON f.film_id = fc.film_id
GROUP BY
a.actor_id;Количество уникальных услуг по полису:
SELECT
cl.policy_id,
COUNT(DISTINCT s.service_code) AS services
FROM
claims AS cl
INNER JOIN services AS s
ON s.claim_id = cl.claim_id
GROUP BY
cl.policy_id;Получение уникальных записей после JOIN
Список городов доставок из заказов через INNER JOIN:
SELECT
DISTINCT a.city
FROM
orders AS o
INNER JOIN addresses AS a
ON a.address_id = o.shipping_address_id
ORDER BY
a.city;Единый реестр поставщиков, задействованных в продажах:
SELECT
DISTINCT s.name
FROM
order_items AS oi
INNER JOIN products AS p
ON p.product_id = oi.product_id
INNER JOIN suppliers AS s
ON s.supplier_id = p.supplier_id
ORDER BY
s.name;Почты пользователей, оставлявших отзывы — без дублей:
SELECT
DISTINCT u.email
FROM
reviews AS r
INNER JOIN users AS u
ON u.user_id = r.user_id
ORDER BY
u.email;Справочник курсов, на которые записывались студенты:
SELECT
DISTINCT c.course_code
FROM
enrollments AS e
INNER JOIN courses AS c
ON c.course_id = e.course_id
ORDER BY
c.course_code;Города клиник, где проходили визиты:
SELECT
DISTINCT cl.city
FROM
visits AS v
INNER JOIN clinics AS cl
ON cl.clinic_id = v.clinic_id
ORDER BY
cl.city;Марки автомобилей, встречающихся в заказах на доставку:
SELECT
DISTINCT car.brand
FROM
deliveries AS d
INNER JOIN cars AS car
ON car.car_id = d.car_id
ORDER BY
car.brand;Контакты менеджеров, фигурирующих в сделках:
SELECT
DISTINCT u.phone
FROM
deals AS d
INNER JOIN users AS u
ON u.user_id = d.owner_id
ORDER BY
u.phone;Перечень складов, откуда отгружались товары:
SELECT
DISTINCT w.name
FROM
shipments AS sh
INNER JOIN warehouses AS w
ON w.warehouse_id = sh.warehouse_id
ORDER BY
w.name;Коды маршрутов, на которых были рейсы:
SELECT
DISTINCT r.route_code
FROM
flights AS f
INNER JOIN routes AS r
ON r.route_id = f.route_id
ORDER BY
r.route_code;Список страховых планов, по которым были выплаты:
SELECT
DISTINCT pl.plan_code
FROM
payouts AS po
INNER JOIN policies AS pl
ON pl.policy_id = po.policy_id
ORDER BY
pl.plan_code;Уникальные комбинации клиент‑валюта из платежей:
SELECT
DISTINCT p.customer_id, p.currency
FROM
payments AS p
ORDER BY
p.customer_id, p.currency;Уникальные пары магазин‑категория из продаж:
SELECT
DISTINCT s.store_id, p.category
FROM
order_items AS oi
INNER JOIN products AS p
ON p.product_id = oi.product_id
INNER JOIN orders AS o
ON o.order_id = oi.order_id
INNER JOIN stores AS s
ON s.store_id = o.store_id
ORDER BY
s.store_id, p.category;Пользователи, встречающиеся в логах авторизации:
SELECT
DISTINCT u.user_id
FROM
logins AS l
INNER JOIN users AS u
ON u.user_id = l.user_id
ORDER BY
u.user_id;Города, из которых делали возвраты товаров:
SELECT
DISTINCT a.city
FROM
returns AS r
INNER JOIN orders AS o
ON o.order_id = r.order_id
INNER JOIN addresses AS a
ON a.address_id = o.shipping_address_id
ORDER BY
a.city;Выделение уникальных значений в подзапросах
Фильтрация клиентов, делавших заказы в разных странах:
SELECT
c.customer_id,
c.full_name
FROM
customers AS c
WHERE
c.customer_id IN (
SELECT
o.customer_id
FROM
orders AS o
INNER JOIN addresses AS a
ON a.address_id = o.shipping_address_id
GROUP BY
o.customer_id
HAVING
COUNT(DISTINCT a.country) >= 2
);Список курсов с участием студентов из разных городов:
SELECT
c.course_id,
c.title
FROM
courses AS c
WHERE
c.course_id IN (
SELECT
e.course_id
FROM
enrollments AS e
INNER JOIN students AS s
ON s.student_id = e.student_id
GROUP BY
e.course_id
HAVING
COUNT(DISTINCT s.city) > 3
);Магазины, где продавались товары из 5 и более брендов:
SELECT
st.store_id,
st.name
FROM
stores AS st
WHERE
st.store_id IN (
SELECT
o.store_id
FROM
orders AS o
INNER JOIN order_items AS oi
ON oi.order_id = o.order_id
INNER JOIN products AS p
ON p.product_id = oi.product_id
GROUP BY
o.store_id
HAVING
COUNT(DISTINCT p.brand) >= 5
);Врачи, у которых были пациенты из ≥ 4 клиник:
SELECT
d.doctor_id,
d.full_name
FROM
doctors AS d
WHERE
d.doctor_id IN (
SELECT
v.doctor_id
FROM
visits AS v
GROUP BY
v.doctor_id
HAVING
COUNT(DISTINCT v.clinic_id) >= 4
);Преподаватели, ведущие в двух и более факультетах:
SELECT
t.teacher_id,
t.teacher_name
FROM
teachers AS t
WHERE
t.teacher_id IN (
SELECT
ct.teacher_id
FROM
course_teachers AS ct
INNER JOIN courses AS c
ON c.course_id = ct.course_id
GROUP BY
ct.teacher_id
HAVING
COUNT(DISTINCT c.faculty_id) >= 2
);Пассажиры с билетами более чем на 3 авиакомпании:
SELECT
p.passenger_id,
p.full_name
FROM
passengers AS p
WHERE
p.passenger_id IN (
SELECT
t.passenger_id
FROM
tickets AS t
GROUP BY
t.passenger_id
HAVING
COUNT(DISTINCT t.airline) > 3
);Клиенты, оплатившие разными способами:
SELECT
c.customer_id,
c.full_name
FROM
customers AS c
WHERE
c.customer_id IN (
SELECT
o.customer_id
FROM
orders AS o
GROUP BY
o.customer_id
HAVING
COUNT(DISTINCT o.payment_method) >= 2
);Пользователи, заходившие с ≥ 3 устройств:
SELECT
u.user_id,
u.email
FROM
users AS u
WHERE
u.user_id IN (
SELECT
l.user_id
FROM
logins AS l
GROUP BY
l.user_id
HAVING
COUNT(DISTINCT l.device_id) >= 3
);Проекты с исполнителями из разных отделов:
SELECT
p.project_id,
p.title
FROM
projects AS p
WHERE
p.project_id IN (
SELECT
a.project_id
FROM
assignments AS a
INNER JOIN employees AS e
ON e.emp_id = a.emp_id
GROUP BY
a.project_id
HAVING
COUNT(DISTINCT e.dept_id) >= 2
);Полисы, по которым обращались из нескольких клиник:
SELECT
pl.policy_id,
pl.plan_code
FROM
policies AS pl
WHERE
pl.policy_id IN (
SELECT
cl.policy_id
FROM
claims AS cl
GROUP BY
cl.policy_id
HAVING
COUNT(DISTINCT cl.clinic_id) >= 2
);Роуты, по которым летали в разные месяцы:
SELECT
r.route_id,
r.route_code
FROM
routes AS r
WHERE
r.route_id IN (
SELECT
f.route_id
FROM
flights AS f
GROUP BY
f.route_id
HAVING
COUNT(DISTINCT f.flight_month) >= 2
);Аккаунты с транзакциями в нескольких валютах:
SELECT
a.account_no
FROM
accounts AS a
WHERE
a.account_no IN (
SELECT
t.account_no
FROM
transactions AS t
GROUP BY
t.account_no
HAVING
COUNT(DISTINCT t.currency) >= 2
);Условные выборки с CASE и DISTINCT
Уникальные категории среди активных товаров — переключение через CASE:
SELECT
DISTINCT CASE WHEN p.is_active = 1 THEN p.category ELSE NULL END AS category_active
FROM
products AS p
WHERE
p.is_active = 1;Пользовательские роли без дублей с нормализацией заглавных букв:
SELECT
DISTINCT CASE WHEN r.role IS NULL THEN 'UNKNOWN' ELSE r.role END AS role_norm
FROM
user_roles AS r;Номер недели из дат заказов — уникальные значения:
SELECT
DISTINCT CASE WHEN o.order_week IS NULL THEN 0 ELSE o.order_week END AS order_week
FROM
orders AS o;Уникальные статусы платежей с подстановкой значения по умолчанию:
SELECT
DISTINCT CASE WHEN p.status IS NULL THEN 'N/A' ELSE p.status END AS status_norm
FROM
payments AS p;Сбор уникальных сегментов лояльности клиентов:
SELECT
DISTINCT CASE WHEN c.loyalty_tier = '' THEN 'NONE' ELSE c.loyalty_tier END AS tier_norm
FROM
customers AS c;Стандартизация формата номера телефона и выбор уникальных:
SELECT
DISTINCT CASE WHEN u.phone LIKE '+%' THEN u.phone ELSE u.phone END AS phone_norm
FROM
users AS u;Выбор уникальных каналов продаж по условию:
SELECT
DISTINCT CASE WHEN s.channel IN ('ONLINE','OFFLINE') THEN s.channel ELSE 'OTHER' END AS ch
FROM
sales AS s;Уникальные уровни срочности задач, включая пустые как ‘NONE’:
SELECT
DISTINCT CASE WHEN t.priority IS NULL THEN 'NONE' ELSE t.priority END AS priority_norm
FROM
tasks AS t;Сопоставление с UNION и UNION ALL
Единый словарь городов из клиентов и поставщиков через UNION:
SELECT DISTINCT city FROM customers
UNION
SELECT DISTINCT city FROM suppliers;Агрегация уникальных валют из счетов и транзакций с UNION:
SELECT DISTINCT currency FROM accounts
UNION
SELECT DISTINCT currency FROM transactions;Список ролей из пользователей и системных ролей:
SELECT DISTINCT role FROM user_roles
UNION
SELECT DISTINCT role FROM system_roles;Общие коды регионов из адресов и складов:
SELECT DISTINCT region_code FROM addresses
UNION
SELECT DISTINCT region_code FROM warehouses;Набор статусов из заказов и доставок:
SELECT DISTINCT status FROM orders
UNION
SELECT DISTINCT status FROM deliveries;Соединение уникальных жанров из фильмов и сериалов:
SELECT DISTINCT genre FROM films
UNION
SELECT DISTINCT genre FROM series;Сортировка уникальных наборов через ORDER BY
Категории по алфавиту:
SELECT
DISTINCT p.category
FROM
products p
ORDER BY
p.category;Города по алфавиту:
SELECT
DISTINCT a.city
FROM
addresses a
ORDER BY
a.city;Курсы по коду:
SELECT
DISTINCT c.course_code
FROM
courses c
ORDER BY
c.course_code;Сортировка уникальных значений — планы по коду:
SELECT
DISTINCT pl.plan_code
FROM
policies pl
ORDER BY
pl.plan_code;Стабильная сортировка уникальных значений — роли по имени:
SELECT
DISTINCT r.role
FROM
user_roles r
ORDER BY
r.role;Отбор уникальных значений — жанры по названию:
SELECT
DISTINCT f.genre
FROM
films f
ORDER BY
f.genre;Прикладные сценарии из реальной практики
E‑commerce: список способов доставки без дублей:
SELECT
DISTINCT o.shipping_method
FROM
orders AS o
ORDER BY
o.shipping_method;Финансы: уникальные типы транзакций в отчёте по движению:
SELECT
DISTINCT tx.kind
FROM
transactions AS tx
ORDER BY
tx.kind;HR: список навыков кандидатов для фильтрации вакансий:
SELECT
DISTINCT c.skill
FROM
candidate_skills AS c
ORDER BY
c.skill;Образование: набор семестров, встречающихся в расписании:
SELECT
DISTINCT sc.semester
FROM
schedule AS sc
ORDER BY
sc.semester;Медицина: уникальные диагнозы из карточек пациентов:
SELECT
DISTINCT pt.diagnosis_code
FROM
patients AS pt
ORDER BY
pt.diagnosis_code;Логистика: маршруты отгрузок без повторов:
SELECT
DISTINCT sh.route_code
FROM
shipments AS sh
ORDER BY
sh.route_code;IoT: список моделей датчиков, поступающих в telemetry:
SELECT
DISTINCT t.sensor_model
FROM
telemetry AS t
ORDER BY
t.sensor_model;CRM: статусы сделок для настройки воронки:
SELECT
DISTINCT d.status
FROM
deals AS d
ORDER BY
d.status;Страхование: коды покрытий по полисам:
SELECT
DISTINCT pl.coverage_code
FROM
policies AS pl
ORDER BY
pl.coverage_code;Retail: наименования отделов магазинов без дублей:
SELECT
DISTINCT s.dept_name
FROM
store_departments AS s
ORDER BY
s.dept_name;Безопасность: перечень типов событий аудита:
SELECT
DISTINCT a.event_type
FROM
audit_log AS a
ORDER BY
a.event_type;Поддержка: тематики обращений клиентов:
SELECT
DISTINCT t.topic
FROM
tickets AS t
ORDER BY
t.topic;Заключение
distinct sql — это набор практик по работе с уникальностями: от простых справочников до сложных аналитических отчётов.Используйте DISTINCT для де‑дупликации результатов, COUNT(DISTINCT …) — для вычисления уникальных количеств, комбинируйте с JOIN, WHERE, GROUP BY, подзапросами и CASE. Держите код читабельным: выравнивайте ключевые слова, сортируйте результаты через ORDER BY и проверяйте планы выполнения для устойчивой производительности.