JavaRush /Курсы /SQL SELF /Поиск данных в массиве: ANY, ALL

Поиск данных в массиве: ANY, ALL, array_contains()

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

Массивы часто используются для хранения нескольких значений в одной колонке — будь то теги, номера, роли или предпочтения. Но как понять, содержится ли в массиве нужное нам значение, или наоборот — все элементы соответствуют определённому условию? PostgreSQL предоставляет удобные средства для таких проверок: ANY, ALL и array_contains(). Разберём каждый из них по порядку.

Что такое ANY?

Представьте, что у вас есть массив, в котором перечислены несколько значений, например, ID товаров, номера телефонов или список хобби. Часто возникает задача проверить, есть ли в массиве определённое значение. Вот тут на сцену выходит оператор ANY. Он позволяет проверить, содержится ли наш "искомый объект" в массиве.

Синтаксис ANY

SELECT *
FROM your_table
WHERE value = ANY(array_column);

Здесь:

  • array_column — это массив, который мы проверяем.
  • value — это значение, которое мы ищем в массиве.

Пример использования ANY

Допустим, у нас есть таблица students со следующей структурой:

id name hobbies
1 Otto {чтение, плавание, шахматы}
2 Eva {музыка, чтение, спорт}
3 Alex {рисование, музыка}
4 Maria {шахматы, футбол}

Нас интересуют студенты, у которых среди хобби есть плавание. Запрос будет выглядеть так:

SELECT *
FROM students
WHERE 'плавание' = ANY(hobbies);

Результат:

id name hobbies
1 Otto {чтение, плавание, шахматы}

Коротко говоря, ANY проверяет: "Есть ли в этом массиве это значение?".

Доверяй, но проверяй всё! Используем ALL

Теперь представьте обратную ситуацию: вам нужно убедиться, что все элементы массива соответствуют определённому правилу. Для этого PostgreSQL предлагает оператор ALL. С его помощью можно проверить, соответствуют ли все элементы массива, например, заданному значению, больше ли они определённого числа или соответствуют любому другому логическому условию.

Синтаксис ALL

SELECT *
FROM your_table
WHERE value < ALL(array_column);

Здесь:

  • array_column — это массив, который мы проверяем.
  • value < ALL(...) означает, что все элементы массива должны быть больше значения.

Вернёмся к нашей таблице students. Допустим, мы хотим найти студентов, у которых все хобби начинаются с буквы "ч". Запрос:

SELECT *
FROM students
WHERE 'чтение' = ALL(hobbies);

Результат будет пустым, потому что ни у кого все хобби не равны слову "чтение". Чтобы пример был более понятным (и работающим), давайте подумаем о числовых данных.

Допустим, есть таблица orders:

id customer prices
1 Otto {100, 200, 300}
2 Eva {50, 60, 70}
3 Alex {500, 600, 700}

Найти все заказы, где каждая позиция дешевле 400:

SELECT *
FROM orders
WHERE 400 > ALL(prices);

Результат:

id customer prices
1 Otto {100, 200, 300}
2 Eva {50, 60, 70}

Фильтрация строк по содержимому массива

Мы разобрали базовые функции и операторы для поиска данных в массивах, но как они применяются на практике? Давайте рассмотрим несколько примеров использования.

Пример 1: Найти студентов, у которых хотя бы одно хобби — музыка

Исходная таблица:

id name hobbies
1 Otto {чтение, музыка, бег}
2 Eva {рисование, плавание}
3 Maria {музыка, бокс}
4 Alex {футбол, бокс, настолки}
SELECT *
FROM students
WHERE 'музыка' = ANY(hobbies);

Результат:

id name hobbies
1 Otto {чтение, музыка, бег}
3 Maria {музыка, бокс}

Пример 2: Найти заказы с ценами более 100 во всех позициях

Исходная таблица orders:

id customer prices
1 Otto {150, 200, 300}
2 Eva {50, 120, 130}
3 Maria {200, 250, 100}
4 Alex {110, 115, 120}
SELECT *
FROM orders
WHERE 100 < ALL(prices);

Результат:

id customer prices
1 Otto {150, 200, 300}
4 Alex {110, 115, 120}

Типичные ошибки и способы их избежать

Когда вы работаете с массивами, особенно для поиска данных, есть несколько подводных камней, которые могут вас подстерегать.

Ошибка: Неправильное использование ANY или ALL. Например, если вы случайно перепутаете операторы, можно получить неожиданные результаты.

-- Неверный вариант:
SELECT *
FROM students
WHERE hobbies = ANY('чтение');

В данном примере ошибка в том, что hobbies — это массив, а 'чтение' — строка. Именно массив должен проверяться с помощью ANY, а не наоборот.

Ошибка: Индексация массивов начинается с 1, а не с 0. Если вы используете массивы в других функциях или пытаетесь извлечь элементы вручную, учитывайте особенности PostgreSQL.

Ошибка: Отсутствие индексации. Если массивы используются для частых операций поиска (ANY, ALL), индексирование может значительно ускорить запросы.

2
Задача
SQL SELF, 35 уровень, 4 лекция
Недоступна
Использование `ANY` для поиска в массиве
Использование `ANY` для поиска в массиве
1
Опрос
Массивы и работа с ними, 35 уровень, 4 лекция
Недоступен
Массивы и работа с ними
Массивы и работа с ними
Комментарии (3)
ЧТОБЫ ПОСМОТРЕТЬ ВСЕ КОММЕНТАРИИ ИЛИ ОСТАВИТЬ КОММЕНТАРИЙ,
ПЕРЕЙДИТЕ В ПОЛНУЮ ВЕРСИЮ
Евгений Уровень 49 Expert
24 сентября 2025
А array_contains в заголовке - это что? Такой функции в Postgres не существует.
Евгений Уровень 49 Expert
24 сентября 2025
Вот здесь так и не объяснили, как правильно найти всех студентов, у кого хобби начинается на "ч":

SELECT *
FROM students
WHERE 'чтение' = ALL(hobbies);
По логике надо использовать LIKE, но мы этого сделать не можем, потому что слева от LIKE указывается проверяемое значение, а справа паттерн, но ALL всегда должен быть справа, так что мы можем использовать LIKE с ALL только в случае, если массив содержит паттерны и мы хотим проверить соответствие значения всем паттернам из массива. А если мы хотим проверить то, что все элементы массива удовлетворяют условию LIKE, то это делается вот так:

CREATE TABLE students
(
    id      SERIAL PRIMARY KEY,
    name    TEXT,
    hobbies TEXT[]
);

INSERT INTO students (name, hobbies)
VALUES ('Ivan', ARRAY ['1', '11', '222']),
       ('Petre', ARRAY ['1', '11', '122']);

SELECT s.name
FROM students AS s
         CROSS JOIN UNNEST(s.hobbies) AS hobby(element)
GROUP BY s.name
HAVING array_position(ARRAY_AGG(hobby.element LIKE '1%'), 'false') IS NULL;
Anonymous #3080756 Уровень 45
8 сентября 2025
Писали, писали и не дописали... А где заявленная в заголовке функция array_contains()? ))))