Оптимизация SQL запроса: удаление дубликатов из LEFT JOIN

Пройдите тест, узнайте какой профессии подходите

Я предпочитаю
0%
Работать самостоятельно и не зависеть от других
Работать в команде и рассчитывать на помощь коллег
Организовывать и контролировать процесс работы

Быстрый ответ

Вы можете исключить дубликаты при выполнении LEFT JOIN, применив простой подход с использованием подзапроса и оконной функции ROW_NUMBER(). Используйте PARTITION BY для столбца, который вызывает дублирование, и затем отберите строки с высшим приоритетом через условие WHERE, исключая таким образом дубликаты.

SQL
Скопировать код
SELECT clean.*
FROM (
    SELECT t1.*, ROW_NUMBER() OVER (PARTITION BY t1.duplicate_field ORDER BY t1.preferred_order) AS row_num
    FROM left_table t1
    LEFT JOIN right_table t2 ON t1.id = t2.foreign_id
) AS clean
WHERE clean.row_num = 1;

Здесь duplicate_field – это столбец, содержащий дубликаты, а preferred_order устанавливает порядок, по которому будут оцениваться дублирующиеся строки.

Кинга Идем в IT: пошаговый план для смены профессии

Применение OUTER APPLY для устранения дублирования

В SQL Server доступна функция OUTER APPLY, которая для каждой строки левой таблицы выполняет подзапрос. Сочетание OUTER APPLY с TOP 1 позволяет выбрать только одну строку из правой таблицы, предотвращая тем самым дублирование.

SQL
Скопировать код
SELECT t1.*, oa.*
FROM left_table t1
OUTER APPLY (
    SELECT TOP 1 *
    FROM right_table t2
    WHERE t1.id = t2.foreign_id
    ORDER BY t2.rank_criteria
) oa;

Эффективность ключевого слова DISTINCT

Если ваш запрос относительно прост, и вы хотите устранить дубликаты после выполнения LEFT JOIN, используйте ключевое слово DISTINCT. Однако стоит обратить внимание на то, что применение DISTINCT может заметно ухудшить производительность при обработке больших объемов данных.

SQL
Скопировать код
SELECT DISTINCT t1.*
FROM left_table t1
LEFT JOIN right_table t2 ON t1.id = t2.foreign_id;

Тонкие настройки с применением выборочного соединения

Когда дело доходит до работы с многомерными таблицами, например, при связывании контента с медиа, важно тщательно выбирать столбцы для объединения, чтобы избегать создания дубликатов:

SQL
Скопировать код
SELECT t1.content_id, t1.title, t2.media_id, t2.url
FROM tbl_Contents t1
LEFT JOIN 
(
    SELECT media_id, content_id, url, ROW_NUMBER() OVER (PARTITION BY content_id ORDER BY priority DESC) as row_num
    FROM tbl_Media
) t2
ON t1.content_id = t2.content_id AND t2.row_num = 1;

Визуализация

Рассмотрим аналогию с очередью в фастфуде:

Markdown
Скопировать код
Очередь (👥): [Боб, Алиса, Тед]
Заказы (🍔📝): [Алиса 🍟, Тед 🌭, Тед 🥤, Алиса 🍔]

LEFT JOIN:
👥💔🍔📝 => [Боб: 🚫, Алиса: 🍟 & 🍔, Тед: 🌭 & 🥤]
# Типично для стандартного LEFT JOIN, что Алиса и Тед "клонируются",
# чтобы отобразить ВСЕ их заказы.

Уникальные заказы:

Markdown
Скопировать код
👥💔🍔📝 => [Боб: 🚫, Алиса: ✅, Тед: ✅]
# В данном случае каждый клиент из левой таблицы (очереди) остается уникальным,
# но все заказы клиента всё равно отображаются.

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

Управление неожиданными NULL и порядком данных

LEFT JOIN может привести к появлению неожиданных NULL и хаосу в порядке данных. Для избежания этого примените следующий подход:

SQL
Скопировать код
SELECT t1.content_id, t1.title, ISNULL(t2.media_id, 'No media') AS media_id
FROM tbl_Contents t1
LEFT JOIN tbl_Media t2 ON t1.content_id = t2.content_id
ORDER BY t1.content_id, t2.priority;

Обеспечение целостности данных

Ваши запросы должны извлекать все соответствующие строки из левой таблицы без дублирования, даже когда в правой таблице есть NULL:

SQL
Скопировать код
SELECT t1.*, COALESCE(t2.attribute, 'Default value') AS attribute
FROM left_table t1
LEFT JOIN right_table t2 ON t1.matching_column = t2.matching_column
WHERE t2.unique_column IS NULL OR t2.unique_column = (/* ваша "золотая" колонка */);

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

Полезные материалы

  1. SQL Joins | Intermediate SQL – Mode — Подробное руководство по работе с Left Join.
  2. SQL LEFT JOIN Keyword – W3Schools — Осваивайте LEFT JOIN с помощью интерактивных примеров.
  3. LEFT JOIN vs LEFT OUTER JOIN – Difference and Comparison | Diffen — Помощь в понимании разницы между LEFT JOIN и LEFT OUTER JOIN.