SQLite SELECT DISTINCT: как убрать дубликаты в запросе

Когда пишешь запросы к реальным таблицам, дубликаты появляются быстрее, чем ожидаешь: один и тот же город у десятка клиентов, повторяющиеся категории, множество NULL в одном столбце. Предложение DISTINCT решает эту задачу в одну строку — и в этой статье я разберу, как именно оно работает и где его применение оправдано

Вся рубрика SQLite: уроки, инструменты и примеры

Синтаксис SELECT DISTINCT в SQLite

Базовый синтаксис выглядит так:

SELECT DISTINCT select_list
FROM table;

Разберём ключевые правила:

Во-первых, предложение DISTINCT должно стоять сразу после ключевого слова SELECT

После DISTINCT указывается один столбец или несколько столбцов. Если выбран только один столбец, SQLite оценивает дублирование по его значениям. При указании нескольких столбцов SQLite анализирует комбинации всех этих значений

SQLite считает значения NULL дубликатами. Если применить DISTINCT к столбцу, содержащему несколько NULL, в результате останется только одна строка с NULL

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

По этой теме полезно отдельно посмотреть EXPLAIN QUERY PLAN: план выполнения SQL-запроса в SQLite, чтобы расширить контекст и сравнить подходы

По этой теме полезно отдельно посмотреть Создание Flutter-приложения с SQLite, BLoC и Streams, чтобы расширить контекст и сравнить подходы

Пример: уникальные города клиентов

Для демонстрации я буду использовать таблицу customers из примера базы данных SQLite

Предположим, нужно узнать, в каких городах находятся клиенты. Сначала выполним запрос без DISTINCT:

SELECT city
FROM customers
ORDER BY city;

Запрос возвращает 59 строк с повторяющимися значениями, такими как Berlin, London и Mountain View. Для устранения дублирования добавляем DISTINCT

SELECT DISTINCT city
FROM customers
ORDER BY city;

Теперь результат содержит 53 строки: предложение DISTINCT удалило 6 дублирующихся строк

Пример: DISTINCT по нескольким столбцам

Следующий запрос выбирает города и страны всех клиентов:

SELECT city, country
FROM customers
ORDER BY country;

Результирующий набор включает дублирующиеся комбинации городов и стран, например, Sao Paulo в Бразилии встречается несколько раз. Для получения уникальных пар используем DISTINCT для обоих столбцов

SELECT DISTINCT city, country
FROM customers
ORDER BY country;

Как я уже отмечал выше, SQLite оценивает дублирование по комбинации значений city и country. Две строки считаются дубликатами только тогда, когда совпадают оба поля одновременно

Как DISTINCT обрабатывает NULL в SQLite

Рассмотрим столбец company в таблице customers:

SELECT company
FROM customers;

Запрос возвращает 59 строк, среди которых много значений NULL. Применим DISTINCT:

SELECT DISTINCT company
FROM customers;

В результате остаётся 11 строк, и NULL встречается только один раз. SQLite группирует все повторяющиеся NULL в одну строку, что соответствует ожидаемому поведению

DISTINCT или GROUP BY: когда что выбрать

Для получения уникальных комбинаций нескольких столбцов с использованием агрегатных функций лучше предпочесть GROUP BY, поскольку DISTINCT удаляет дубликаты на уровне строк, тогда как GROUP BY позволяет группировать строки

Пример с GROUP BY для сравнения:

SELECT city, COUNT(*) AS customer_count
FROM customers
GROUP BY city
ORDER BY city;

Такой запрос не только покажет уникальные города, но и сообщит, сколько клиентов в каждом из них

Типичные ошибки при работе с DISTINCT

На практике я встречал несколько распространённых заблуждений, которые стоит разобрать отдельно

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

DISTINCT не заменяет индексы. На больших таблицах запрос с DISTINCT может работать медленно при отсутствии подходящего индекса по столбцам выборки. Оптимизацию следует проводить с использованием плана выполнения запроса, проверив его с помощью EXPLAIN QUERY PLAN

Важно понимать, что NULL и пустая строка не являются одним и тем же значением; DISTINCT оставит одну строку с NULL, отдельной от строк с пустой строкой ''

Предложение SELECT DISTINCT в SQLite — простой и надёжный способ получить уникальные значения из одного или нескольких столбцов. Главное помнить: DISTINCT работает со всем набором перечисленных столбцов, а NULL трактуется как дубликат и схлопывается в одну строку

Ответы на эти вопросы могут быть для вас полезными

Можно ли использовать DISTINCT с агрегатными функциями? Да. Например, SELECT COUNT(DISTINCT city) FROM customers вернёт количество уникальных городов, а не общее число строк

Влияет ли порядок столбцов после DISTINCT на результат? Нет, порядок столбцов в списке SELECT DISTINCT не влияет на то, какие строки считаются дубликатами — важна только комбинация значений

Как DISTINCT обрабатывает несколько значений NULL в одном столбце? SQLite считает все NULL одинаковыми, поэтому в результате останется только одна строка с NULL, остальные будут удалены

Чем DISTINCT отличается от GROUP BY без агрегации? На практике SELECT DISTINCT col FROM t и SELECT col FROM t GROUP BY col дают одинаковый результат. Разница проявляется при добавлении агрегатных функций: GROUP BY их поддерживает, DISTINCT — нет

Работает ли DISTINCT в подзапросах? Да. DISTINCT можно использовать внутри подзапроса точно так же, как и в основном запросе, — синтаксис и поведение не меняются

Оцените статью
0 0 голоса
Рейтинг статьи
Подписаться
Уведомить о
guest

0 комментариев
Старые
Новые Популярные
Межтекстовые Отзывы
Посмотреть все комментарии
0
Оставьте комментарий! Напишите, что думаете по поводу статьи.x