Track
Операции с множествами лежат в основе SQL и позволяют объединять, сравнивать и фильтровать данные из нескольких источников. Эти операции незаменимы для задач от интеграции и очистки данных до продвинутой аналитики и отчетности.
В этом руководстве мы разберем, что такое операторы множеств, как они используются в SQL, их практические сценарии и многое другое. Если вам нужен полный ресурс по изучению SQL, посмотрите этот из семи курсов SQL Fundamentals.
Для тех, кто спешит, начнем с очень короткого ответа о том, что такое операции множеств в SQL.
Что такое операции множеств в SQL?
Операции множеств в SQL — это приемы объединения или сравнения результатов двух и более операторов SELECT. Они работают как математические операции над множествами, позволяя находить объединение, пересечение или разность между строками, возвращаемыми запросами. Это делает их незаменимыми при анализе данных из нескольких источников или с разных точек зрения.
Краткий обзор основных операций множеств:
-
UNION: Объединяет все уникальные строки из двух и более операторовSELECT, удаляя дубликаты. -
UNION ALL: Объединяет все строки из двух и более операторовSELECT, сохраняя дубликаты. -
INTERSECT: Возвращает только те строки, которые присутствуют в обоих операторахSELECT. -
EXCEPT: Возвращает строки из первого оператораSELECT, которых нет во втором.
Сравнение с операциями реляционной алгебры
Реляционная алгебра — это теоретическая основа для понимания запросов к базам данных. Она предлагает абстрактные операции, такие как проекция, выборка и соединение, основанные на математических принципах и независимые от конкретных СУБД. Можно считать ее «закулисной» логикой, которая приводит в действие наши взаимодействия с базой данных.
Операторы множеств в SQL — это практическая реализация этих концепций в среде базы данных. Они позволяют выполнять операции объединения, пересечения и разности непосредственно над результатами SQL-запросов.
В то время как реляционная алгебра дает формальные основы для операций с данными, операторы множеств в SQL предоставляют стандартизированный и удобный интерфейс для задач манипулирования данными.
Понимание связи между операторами множеств и операциями реляционной алгебры помогает глубже понять теоретические основы SQL. Это знание позволяет писать запросы с более ясной ментальной моделью происходящего «под капотом».
Типы операторов множеств в SQL
В SQL есть три основных оператора множеств:
-
UNION -
INTERSECT -
EXCEPT(илиMINUSв некоторых диалектах)
Эти операторы математически соответствуют понятиям объединения, пересечения и разности множеств.
Правила использования операторов множеств
Перед объединением запросов с помощью операторов множеств необходимо выполнить четыре условия. Ошибка в любом из них приведет к сбою запроса.
-
Одинаковое количество столбцов: Каждый
SELECTдолжен возвращать одинаковое число столбцов. Если один запрос возвращает три, а другой — два, СУБД выдаст ошибку. -
Совместимые типы данных: Соответствующие столбцы должны иметь согласованные типы. Нельзя объединить столбец имени типа
VARCHARи столбец идентификатора типаINTEGERв одной позиции. -
Одинаковый порядок столбцов: SQL сопоставляет столбцы по позиции, а не по имени. Первый столбец первого запроса сопоставляется с первым столбцом второго, независимо от их названий.
-
ORDER BYтолько в конце:ORDER BYдолжен присутствовать один раз — в самом конце объединенного запроса. Нельзя использовать его внутри отдельных операторовSELECT.
Еще одна деталь: имена столбцов в выводе берутся из первого оператора SELECT. Псевдонимы в последующих запросах игнорируются, поэтому добавляйте их только к первому запросу, если вам нужны свои названия столбцов.
Как использовать оператор UNION в SQL
Оператор UNION объединяет результаты двух и более запросов SELECT в один набор результатов, по умолчанию удаляя дубликаты строк.
Допустим, у нас есть две таблицы — employees и contractors — каждая с похожими столбцами, такими как contractors, department и salary. Для обучения возьмем две демонстрационные таблицы:
employees:
|
name |
department |
salary |
|
Alice |
Marketing |
65000 |
|
Bob |
Sales |
70000 |
|
Carol |
Engineering |
80000 |
|
John |
HR |
55000 |
contractors:
|
name |
department |
salary |
|
David |
Marketing |
60000 |
|
Eva |
Sales |
68000 |
|
Carol |
Engineering |
75000 |
Мы можем объединить результаты обеих таблиц следующим образом:
-- Using UNION to combine all employees and contractors
SELECT name, department, salary FROM employees
UNION
SELECT name, department, salary FROM contractors;
Этот запрос выбирает столбцы name, department и salary из таблиц employees и contractors и объединяет их в один набор результатов. Оператор UNION автоматически удаляет дубликаты строк из итогового набора.
|
name |
department |
salary |
|
Alice |
Marketing |
65000 |
|
Bob |
Sales |
70000 |
|
Carol |
Engineering |
80000 |
|
John |
HR |
55000 |
|
David |
Marketing |
60000 |
|
Eva |
Sales |
68000 |
Обратите внимание: Каролина (Carol), которая есть в обеих таблицах, в результате указана только один раз. Если нам нужно оставить оба случая (с разными зарплатами), следует использовать UNION ALL.
UNION vs UNION ALL
Оператор UNION не удаляет значения NULL. Если в одном наборе результатов столбец содержит NULL, а в соответствующем столбце другого набора — не-NULL значения, то NULL будут сохранены в итоговом наборе, сформированном оператором UNION.
Если мы хотим включить значения NULL в набор результатов и предотвратить их удаление оператором UNION, можно использовать UNION ALL. Этот оператор объединяет результаты нескольких запросов SELECT, включая все строки из каждого набора, независимо от дубликатов и наличия NULL.
Как использовать оператор INTERSECT в SQL
Оператор INTERSECT возвращает только те строки, которые присутствуют в обоих наборах результатов. Представьте, что мы находим людей, принадлежащих к обеим группам.
Давайте применим INTERSECT к нашим таблицам выше. Для простоты выберем только столбцы name и department:
-- Using INTERSECT to find common employees
SELECT name, department FROM employees
INTERSECT
SELECT name, department FROM contractors;
Этот запрос выбирает столбцы name и department из таблиц employees и contractors и возвращает только те строки, которые существуют в обеих таблицах на основании всех выбранных столбцов.
|
name |
department |
|
Carol |
Engineering |
Оператор INTERSECT обрабатывает NULL в соответствии со стандартными правилами сравнения, считая NULL равными при сравнении соответствующих столбцов. При работе с пустыми наборами результатов он также выдает пустой набор.
Иными словами, если в одном наборе результатов есть значение NULL, а в соответствующем столбце другого набора — не-NULL, строки не считаются равными и не попадут в результат пересечения.
Кроме того, если один из наборов результатов, переданных оператору INTERSECT, пуст, общий результат также будет пустым. Общих строк между пустым множеством и чем-либо еще не существует.
Как использовать оператор UNION в SQL
Оператор EXCEPT возвращает строки из первого набора результатов, которых нет во втором.
В Oracle Database EXCEPT записывается как MINUS; все прочие основные диалекты (PostgreSQL, SQL Server, MySQL 8.0.31+, SQLite) используют EXCEPT.
Например, выполним следующий запрос:
-- Using EXCEPT to find employees who are not contractors
SELECT name, department, salary FROM employees
EXCEPT
SELECT name, department, salary FROM contractors;
Из таблицы employees выбираются столбцы name, department и salary, и возвращаются только те строки, которых нет в таблице contractors.
|
name |
department |
salary |
|
Alice |
Marketing |
65000 |
|
Bob |
Sales |
70000 |
|
John |
HR |
55000 |
Оператор EXCEPT также следует стандартным правилам сравнения для обработки NULL. Его поведение с пустыми наборами результатов таково: если первый набор пуст, результат пуст; если второй набор пуст, возвращаются все строки из первого набора.
Операторы множеств в SQL: производительность и оптимизация
Влияние операторов множеств на производительность запросов в SQL может различаться в зависимости от размера задействованных наборов данных, сложности запросов и используемой системы управления базами данных (СУБД).
Разберем ключевые факторы и стратегии оптимизации.
Объем данных и сложность запросов
При работе с большими объемами данных операторы множеств могут заметно влиять на производительность, поскольку увеличение размеров объединяемых, пересекаемых или сравниваемых наборов повышает время обработки для выполнения операции.
Сложные запросы, содержащие несколько подзапросов, соединений или операторов множеств, могут создавать дополнительную нагрузку и ухудшать производительность. Последовательные или вложенные операции множеств могут еще больше усугубить последствия.
Индексация и приемы оптимизации
Правильная индексация столбцов, участвующих в операциях множеств, может существенно повысить производительность запросов. Индексы помогают движку базы данных быстро находить и извлекать нужные строки, снижая необходимость полноскановых проходов по таблице и ускоряя выполнение.
Чтобы улучшить работу запросов с операторами множеств, администраторы и разработчики могут применять такие техники, как переписывание запросов, анализ планов выполнения и оптимизация схемы. Также можно использовать кэширование запросов и материализованные представления, чтобы заранее вычислять и сохранять результаты сложных запросов, уменьшая вычислительные затраты.
Движок базы данных и аппаратные ресурсы
Производительность операций множеств может варьироваться в зависимости от движка базы данных и его возможностей оптимизации. Разные СУБД применяют разные стратегии и алгоритмы обработки таких операций, что приводит к различиям в скорости.
Доступность аппаратных ресурсов, таких как CPU, память и дисковый ввод-вывод, также влияет на производительность запросов с операторами множеств. Достаточные ресурсы помогают смягчить «узкие места» и обеспечить эффективное выполнение.
Операторы множеств на практике
Операторы множеств — это не только теория; у них есть прикладные сценарии, которые могут существенно влиять на бизнес-решения. Рассмотрим упрощенный пример того, как компания может использовать их для сегментации клиентской базы под таргетированные маркетинговые кампании.
Сценарий
Представьте компанию, которая продает онлайн и в офлайн-магазинах. У нее есть два отдельных набора данных:
- Онлайн-покупки: идентификатор клиента, история покупок, демография и местоположение онлайн-покупателей.
- Офлайн-транзакции: аналогичная информация для клиентов, совершавших покупки в магазинах.
Использование операторов множеств
Чтобы получить полную картину всех клиентов, компания сначала применит UNION для объединения обоих наборов данных в единую таблицу, удалив дубликаты. Это даст целостный вид всей клиентской базы.
Затем можно использовать INTERSECT, чтобы определить клиентов, совершавших покупки и онлайн, и офлайн. Этот сегмент особенно ценен, поскольку такие клиенты активно взаимодействуют с брендом по нескольким каналам.
Чтобы найти возможности для кросс-канального продвижения, компания может применить EXCEPT. Например, SELECT * FROM online_purchases EXCEPT SELECT * FROM in_store_transactions выявит клиентов, покупавших только онлайн, но не в магазинах. Этим клиентам можно предложить акции, стимулирующие визит в офлайн-точку.
За рамками сегментации
Определив сегменты, компания может пойти дальше и уточнить их на основе дополнительных факторов — демографии или истории покупок. Такое детальное понимание клиентов позволяет точнее настраивать маркетинговые кампании.
Операторы множеств vs. JOIN
И операторы множеств, и SQL JOIN объединяют данные из нескольких запросов, но работают по-разному. Ключевой вопрос — вы хотите объединить строки или столбцы?
| Feature | Set Operators | JOINs |
|---|---|---|
| Combines | Rows (stacks queries vertically) | Columns (widens rows horizontally) |
| Requires | Same column count and compatible data types | A shared key column between tables |
| Use when | Merging similar datasets, finding overlaps or differences between result sets | Enriching a row with related data from another table |
| Duplicate handling | UNION removes duplicates; UNION ALL keeps them |
Depends on join type and the data |
| Types | UNION, UNION ALL, INTERSECT, EXCEPT/MINUS |
INNER, LEFT, RIGHT, FULL OUTER, CROSS |
Ограничения и особенности операторов множеств
При использовании операторов множеств в SQL важно учитывать ряд ограничений и факторов, влияющих на производительность запросов, точность результатов и удобство использования.
Совместимость типов данных и значения NULL
Соответствующие столбцы в наборах результатов должны иметь совместимые типы данных. Убедитесь, что соответствующие столбцы совместимы по типам, прежде чем объединять запросы. Несоответствие типов вызывает ошибки, которые легко упустить.
Операторы множеств могут по-разному трактовать значения NULL в зависимости от СУБД и конкретного оператора. Чтобы избежать ошибок, разработчикам важно понимать, как обрабатываются NULL.
Влияние на производительность и дублирующиеся строки
Операции множеств могут заметно влиять на производительность, особенно при работе с большими или сложными наборами данных. На скорость влияют индексация, оптимизация запросов и аппаратные ресурсы. Для снижения узких мест необходимы техники оптимизации и настройки производительности.
По умолчанию операторы множеств удаляют дубликаты строк из результата. Однако в некоторых случаях сохранение дубликатов необходимо. Важно понимать поведение операторов в отношении дубликатов и применять соответствующие приемы при необходимости.
Сортировка результатов и ограничения по памяти
Операторы множеств не гарантируют порядок строк в итоговом выводе. Чтобы отсортировать объединенный результат, добавьте ORDER BY в самом конце всего запроса, после последнего оператора SELECT.
Операции множеств могут потреблять значительные объемы памяти и ресурсов, особенно при работе с большими наборами данных. Следует учитывать ограничения памяти и ресурсов, чтобы избежать деградации производительности или нестабильности системы.
Сложность, сопровождаемость и кросс-СУБД совместимость
Сложные запросы с несколькими операторами множеств, подзапросами и соединениями трудно понимать, сопровождать и отлаживать. Для лучшей читаемости и сопровождаемости запросы должны быть лаконичными, хорошо документированными и модульными.
Синтаксис и поведение операторов множеств могут различаться в разных системах управления базами данных. Знание этих различий важно для написания SQL-запросов с учетом межплатформенной совместимости.
Заключение
Операторы множеств решают конкретную задачу: объединять или сравнивать наборы результатов, не зная заранее, какие строки пересекаются.
Они охватывают UNION, INTERSECT и EXCEPT — три оператора для объединения, сравнения и вычитания наборов результатов.
Если хотите узнать больше, посмотрите курс Joining Data in SQL.
Частые вопросы по операторам SQL
В чем разница между UNION ALL и UNION?
UNION ALL включает все строки из обоих запросов, даже если есть дубликаты. UNION удаляет дубликаты строк.
Чем UNION отличается от JOIN в SQL?
UNION объединяет результаты запросов по вертикали, добавляя строки одного запроса к другому. JOIN объединяет таблицы по горизонтали, сопоставляя строки по связанному столбцу и формируя более широкий набор результатов.
Есть ли соображения по производительности при использовании операций множеств?
Операции множеств могут быть ресурсоемкими, особенно при работе с большими наборами данных. Важно оптимизировать отдельные запросы и использовать индексы там, где это возможно, чтобы повысить производительность.
В чем разница между EXCEPT и NOT IN?
EXCEPT и NOT IN могут давать схожие результаты, но по-разному обращаются с NULL. EXCEPT считает значения NULL равными при сравнении строк, поэтому две записи с NULL в одной и той же позиции приведут к исключению строки. NOT IN, напротив, не вернет ни одной строки, если подзапрос содержит хотя бы одно значение NULL, поскольку сравнения с NULL в SQL не определены. Для больших наборов данных EXCEPT также может быть более читаемым, чем коррелированный подзапрос с NOT IN.
Можно ли использовать ORDER BY с операторами множеств?
Да, но только один раз — в самом конце всего запроса. Нельзя использовать ORDER BY внутри отдельных операторов SELECT в составе операции множеств. Чтобы отсортировать объединенный результат, добавьте единственный оператор ORDER BY после последнего SELECT.
Пример:
SELECT name FROM employees
UNION
SELECT name FROM contractors
ORDER BY name ASC;Поддерживает ли MySQL операторы INTERSECT и EXCEPT?
MySQL добавил поддержку INTERSECT и EXCEPT в версии 8.0.31. Если у вас более старая версия, их придется эмулировать: используйте INNER JOIN или подзапрос с IN для INTERSECT, а также LEFT JOIN ... WHERE IS NULL или подзапрос с NOT IN для EXCEPT. В Oracle используется MINUS вместо EXCEPT.