AND, OR, NOT
Логические операторы для составления более точных условий
Теория
До этого мы фильтровали строки по одному условию: например, показать только товары дороже определённой суммы или только пользователей из конкретного города. Однако на практике для получения нужных строк одного условия часто бывает мало.
Например, может понадобиться:
• показать работников из отдела продаж с зарплатой выше 90000;
• найти пользователей из Москвы или Алматы;
• исключить из выборки отменённые заказы дороже определенного значения;
• выбрать товары из одной группы условий, но исключить другую.
В SQL для этого есть логические операторы:
• AND — когда должны выполняться сразу все условия;
• OR — когда достаточно хотя бы одного условия;
• NOT — когда нужно перевернуть условие, то есть наоборот исключить его.
Другими словами AND — это «И одновременно», OR — это «ИЛИ хотя бы одно», а NOT — это «НЕ».
Это немного сложнее, чем фильтрация по одному условию, так как достаточно просто запутаться, если условий много, поэтому самое важное здесь — почувствовать эту логику. SQL проверяет условие для каждой строки отдельно. Если строка подходит под вашу комбинацию условий, она попадает в результат. Если нет — отбрасывается.
Пример: Представьте, что вы ищите пользователей по фамилии 'Иванов', проживающих в городе 'Москва'. Это два условия. За фамилии здесь отвечает столбец last_name, а за города city. Таким образом в запросе вам нужно будет комбинировать оба условия и в данном случае через оператор AND.
Увидев это PostgreSQL для каждой строки будет проверять выполнения обоих условий, если хоть одно не будет выполнено строка в результат не попадет. Допустим пользователь по фамилии 'Иванов', проживающей в 'Казань' в результат не попадет. Так как для него выполнено только одно из обязательных условий, фамилия 'Иванов'. А вот если вместо AND написать OR то попадет. Потому что для логического оператора OR важно, чтобы было выполнено хотя бы одно условие, находящееся справа или слева от него.
Например, может понадобиться:
• показать работников из отдела продаж с зарплатой выше 90000;
• найти пользователей из Москвы или Алматы;
• исключить из выборки отменённые заказы дороже определенного значения;
• выбрать товары из одной группы условий, но исключить другую.
В SQL для этого есть логические операторы:
• AND — когда должны выполняться сразу все условия;
• OR — когда достаточно хотя бы одного условия;
• NOT — когда нужно перевернуть условие, то есть наоборот исключить его.
Другими словами AND — это «И одновременно», OR — это «ИЛИ хотя бы одно», а NOT — это «НЕ».
Это немного сложнее, чем фильтрация по одному условию, так как достаточно просто запутаться, если условий много, поэтому самое важное здесь — почувствовать эту логику. SQL проверяет условие для каждой строки отдельно. Если строка подходит под вашу комбинацию условий, она попадает в результат. Если нет — отбрасывается.
Пример: Представьте, что вы ищите пользователей по фамилии 'Иванов', проживающих в городе 'Москва'. Это два условия. За фамилии здесь отвечает столбец last_name, а за города city. Таким образом в запросе вам нужно будет комбинировать оба условия и в данном случае через оператор AND.
Увидев это PostgreSQL для каждой строки будет проверять выполнения обоих условий, если хоть одно не будет выполнено строка в результат не попадет. Допустим пользователь по фамилии 'Иванов', проживающей в 'Казань' в результат не попадет. Так как для него выполнено только одно из обязательных условий, фамилия 'Иванов'. А вот если вместо AND написать OR то попадет. Потому что для логического оператора OR важно, чтобы было выполнено хотя бы одно условие, находящееся справа или слева от него.
Синтаксис
SELECT column1, -- указываем столбцы, которые хотим получить
column2,
column3
FROM table_name -- указываем таблицу, из которой берём данные
WHERE condition1 AND condition2; -- оставляем строки, где выполняются оба условия
SELECT column1,
column2,
column3
FROM table_name
WHERE condition1 OR condition2; -- оставляем строки, где выполняется хотя бы одно условие
SELECT column1,
column2,
column3
FROM table_name
WHERE NOT condition; -- оставляем строки, где условие не выполняется
SQL
AND, OR и NOT пишутся внутри WHERE между условиями или перед условием.
Коротко по смыслу:
• AND — строка должна пройти все проверки сразу;
• OR — строке достаточно пройти хотя бы одну проверку;
• NOT — меняет условие на противоположное.
Важно помнить и про порядок выполнения:
• сначала SQL обрабатывает NOT;
• потом AND;
• и только потом OR.
Если вы смешиваете AND и OR в одном запросе, почти всегда лучше ставить скобки для приоритетности нужных условий. Так ваш запрос будет выдавать более предсказуемый результат.
Коротко по смыслу:
• AND — строка должна пройти все проверки сразу;
• OR — строке достаточно пройти хотя бы одну проверку;
• NOT — меняет условие на противоположное.
Важно помнить и про порядок выполнения:
• сначала SQL обрабатывает NOT;
• потом AND;
• и только потом OR.
Если вы смешиваете AND и OR в одном запросе, почти всегда лучше ставить скобки для приоритетности нужных условий. Так ваш запрос будет выдавать более предсказуемый результат.
Примеры
1. Оставляем только нужных работников
В этом примере должны одновременно выполняться оба условия: работник должен быть из отдела 1 и при этом получать не меньше 90000. Если хотя бы одно условие не выполняется, строка не попадёт в результат.
🔄 Попробуйте изменить запрос:
- • Поменяйте 90000 на 70000 и сравните выборку
- • Поменяйте AND на OR и посмотрите, насколько больше строк попадет в результат
2. Ищем пользователей из одного города или другого
Здесь логика другая: строке достаточно подойти хотя бы под одно условие. Пользователь попадёт в результат, если его город — 'Москва' или 'Алматы'.
🔄 Попробуйте изменить запрос:
- • Замените один из городов на 'Санкт-Петербург'
- • Попробуйте OR заменить на AND и объяснить пустой результат
3. Исключаем дорогие товары
Этот запрос берёт товары, цена которых не больше 100000. Здесь NOT переворачивает условие price > 100000.
🔄 Попробуйте изменить запрос:
- • Замените условие на NOT price < 100000 и посмотрите, как изменится выборка
- • Перепишите запрос без NOT, используя прямое, а не обратное сравнение
4. Скобки меняют смысл запроса
Сначала скобки собирают пользователей из 'Москвы' и 'Алматы', а потом к уже этой группе применяется условие по дате регистрации. Без скобок логика запроса будет другой, и в выборку попадет больше строк, чем вы ожидаете.
🔄 Попробуйте изменить запрос:
- • Уберите скобки и сравните результат
- • Попробуйте добиться такого же результата, как в примере, но не используя скобки, а используя только логические операторы AND и OR
Типичные ошибки
Смешивают AND и OR без скобок
Это самая частая ошибка. Кажется, что запрос читается «как на русском языке», но SQL сначала выполнит AND, а потом OR. Комбинируя эти логические операторы в одном запросе, лучше явно расставлять скобки.
Ставят AND там, где условие физически не может выполниться
Например, city = 'Москва' AND city = 'Алматы'. Одна и та же строка не может одновременно иметь два разных значения в одном столбце. В таких случаях обычно нужен OR.
Используют NOT там, где прямое условие было бы понятнее
Запрос NOT price > 100000 работает, но иногда запись price <= 100000 читается проще. Если без NOT условие становится логично понятнее, лучше так и написать.
Забывают полностью повторить условие после OR
WHERE city = 'Москва' OR 'Алматы' приведет к ошибке синтаксиса. Нужно писать полностью: city = 'Москва' OR city = 'Алматы'.
Практика
Проверь себя
Ответьте на вопросы, чтобы закрепить материал:
1
Что означает условие department_id = 1 AND salary >= 90000?
2
Какой смысл у условия city = 'Москва' OR city = 'Алматы'?
3
Какой вариант лучше всего передаёт смысл условия NOT price > 100000?
4
Напишите запрос, который выведет product_name, category и price товаров, у которых категория не указана или цена ниже 90000. Результат отсортируйте по цене от большей к меньшей.
5
Какой порядок выполнения у логических операторов в SQL по умолчанию?
6
Как SQL поймёт условие без скобок: department_id = 1 OR department_id = 2 AND salary >= 90000?
7
Напишите запрос, который выведет order_id, user_id, status и order_date заказов, которые либо ещё без статуса, либо не отменены и оформлены после '2024-04-10'. Более новые заказы должны идти выше.
8
Сколько строк вернёт запрос к таблице orders, если выбрать заказы без статуса, у которых дата заказа раньше '2024-04-10' или не раньше '2024-04-18'? Введите только число.
9
Какое из этих условий логически невозможно для одной строки?