JavaRush /Курсы /SQL SELF /Сравнение и фильтрация массивов: =, @>, <@, &&a...

Сравнение и фильтрация массивов: =, @>, <@, &&

SQL SELF
36 уровень , 1 лекция
Открыта

Иногда возникают сценарии, где нужно понять, содержится ли одно множество значений в другом, пересекаются ли они, равны ли они или являются подмножествами друг друга. Например:

  • Есть ли у пользователя доступ к определенным категориям?
  • Какие товары имеют общие теги?
  • Какие массивы содержат все перечисленные значения?

Эти задачи решаются с помощью операторов сравнения массивов в PostgreSQL: =, @>, <@ и &&. Мы окунемся в каждый из этих операторов и разберем их на примерах.

= — Сравнение массивов на равенство

Этот оператор используется, чтобы проверить, идентичны ли два массива. Условие вернет TRUE, если оба массива имеют одинаковую длину и одинаковый набор элементов в точно таком же порядке.

Пример:

SELECT ARRAY[1, 2, 3] = ARRAY[1, 2, 3] AS are_equal;  -- TRUE
SELECT ARRAY[1, 2, 3] = ARRAY[3, 2, 1] AS are_equal;  -- FALSE

Особенность: порядок элементов имеет значение. Массив [1, 2, 3] не равен [3, 2, 1].

@> — Массив содержит другой массив

Этот оператор проверяет, содержит ли массив все элементы другого массива (независимо от порядка). Часто используется для задач, где нужно удостовериться, что все искомые элементы присутствуют.

Пример:

SELECT ARRAY[1, 2, 3] @> ARRAY[1, 2] AS contains;  -- TRUE
SELECT ARRAY[1, 2, 3] @> ARRAY[4] AS contains;     -- FALSE

Полезный сценарий: проверка прав доступа. Например, вы хотите убедиться, что определенная роль включает все необходимые разрешения.

<@ — Массив является подмножеством другого массива

Противоположность оператора @>. Проверяет, содержится ли массив полностью в другом массиве.

Пример:

SELECT ARRAY[1, 2] <@ ARRAY[1, 2, 3] AS is_subset;  -- TRUE
SELECT ARRAY[4] <@ ARRAY[1, 2, 3] AS is_subset;     -- FALSE

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

&& — Пересечение массивов

Этот оператор проверяет, пересекаются ли два массива, то есть имеют ли они хотя бы один общий элемент.

Пример:

SELECT ARRAY[1, 2, 3] && ARRAY[3, 4, 5] AS intersects;  -- TRUE
SELECT ARRAY[1, 2, 3] && ARRAY[6, 7, 8] AS intersects;  -- FALSE

Полезный сценарий: поиск товаров или записей, имеющих общие категории или характеристики.

Использование операторов в фильтрации данных

Давайте применим эти операторы для фильтрации данных в таблице. Например, у нас есть таблица products со столбцом tags, содержащим массив тегов для каждого товара.

Пример таблицы products

id name tags
1 "Product A" {electronics, sale}
2 "Product B" {home, sale}
3 "Product C" {electronics, new}
4 "Product D" {home, garden}

Найдем все товары, которые имеют тег electronics.

SELECT *
FROM products
WHERE tags @> ARRAY['electronics'];

Результат:

id name tags
1 "Product A" {electronics, sale}
3 "Product C" {electronics, new}

Хотим найти товары, у которых теги ровно {home, sale}.

SELECT *
FROM products
WHERE tags = ARRAY['home', 'sale'];

Результат:

id name tags
2 "Product B" {home, sale}

А теперь давайте

найдем товары, у которых есть хотя бы один из тегов {sale, new}.
SELECT *
FROM products
WHERE tags && ARRAY['sale', 'new'];

Результат:

id name tags
1 "Product A" {electronics, sale}
2 "Product B" {home, sale}
3 "Product C" {electronics, new}

Ищем товары, где теги точно ограничиваются {home, garden}.

SELECT *
FROM products
WHERE tags <@ ARRAY['home', 'garden'];

Результат:

id name tags
4 "Product D" {home, garden}

Пример: проверка содержимого списков с CASE

Мы можем объединить сравнение массивов с условными выражениями. Например, создадим запрос, который метит товары, содержащие тег sale, как "Скидка", а остальные — как "Без скидки":

SELECT name,
       CASE
         WHEN tags @> ARRAY['sale'] THEN 'Скидка'
         ELSE 'Без скидки'
       END AS discount_status
FROM products;

Результат:

name discount_status
"Product A" Скидка
"Product B" Скидка
"Product C" Без скидки
"Product D" Без скидки

Типичные ошибки и их предотвращение

Ошибка: неправильное использование порядка элементов в операторе =. Помните, что = требует точного соответствия порядка элементов. Если порядок не важен, используйте @> или &&.

Ошибка: несоответствие типов данных. Массивы должны быть одного типа. Например, ARRAY['1', '2'] не равен ARRAY[1, 2], так как первый массив строковый, а второй — числовой. Всегда проверяйте типы перед сравнением.

Ошибка: отсутствие индексов. Если вы часто фильтруете строки по массивам, обязательно создавайте индексы (GIN) для повышения производительности.

Эти операторы позволяют реализовать мощную фильтрацию и сравнение данных, которые часто встречаются в реальных проектах: от анализа тегов товаров до управления правами доступа. Используя их эффективно, вы сможете упростить сложные задачи и оптимизировать работу ваших запросов.

2
Задача
SQL SELF, 36 уровень, 1 лекция
Недоступна
Проверка содержимого массива с помощью оператора `@>`
Проверка содержимого массива с помощью оператора `@>`
Комментарии (1)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Евгений Уровень 49 Expert
25 сентября 2025
Любопытно, что следующий запрос возвращает true:

SELECT ARRAY [1, 2] @> ARRAY [2, 2, 2, 1, 1, 1, 1];
Т.е. оператор проверяет вхождение уникальных элементов, игнорируя при этом порядок.