Приоритет операторов и скобки
Приоритет операторов и скобки
В уроке про AND, OR и NOT мы кратко затронули тему приоритета операторов. Это достаточно важная тема, чтобы посвятить ей отдельный урок. Ошибки с приоритетом операторов особенно коварны: запрос выполняется без ошибок, возвращает данные, но не те, которые вы ожидали. Такие баги сложно заметить и легко пропустить.
Что такое приоритет операторов
Приоритет — это порядок, в котором операторы вычисляются, когда в одном выражении их несколько. Вы знаете это из математики: 2 + 3 * 4 равно 14, а не 20, потому что умножение имеет более высокий приоритет, чем сложение.
В SQL та же идея применяется к логическим операторам в WHERE. Когда вы пишете составное условие без скобок, SQL вычисляет его по правилам приоритета, а не слева направо.
Иерархия приоритетов в SQL
От высшего к низшему:
| Приоритет | Операторы |
|---|---|
| Высший | Арифметика: *, /, % |
Сложение/вычитание: +, - | |
Операторы сравнения: =, <>, <, >, <=, >= | |
IS [NOT] NULL, LIKE, BETWEEN, IN | |
NOT | |
AND | |
| Низший | OR |
Ключевое правило: AND выполняется до OR. NOT выполняется до AND.
Пример: AND перехватывает OR
Рассмотрим знакомый пример:
SELECT * FROM employees
WHERE department = 'Разработка'
OR department = 'Дизайн'
AND salary > 80000;
Из-за приоритета (AND раньше OR) это читается как:
WHERE department = 'Разработка'
OR (department = 'Дизайн' AND salary > 80000)
Результат: все разработчики (без ограничений по зарплате) ПЛЮС дизайнеры с зарплатой выше 80000.
Если вы хотели «разработчики или дизайнеры, но только с зарплатой выше 80000», нужны скобки:
WHERE (department = 'Разработка' OR department = 'Дизайн')
AND salary > 80000
Два внешне похожих запроса дают принципиально разные результаты. Именно поэтому скобки — не опциональный стиль, а защита от ошибок.
Пример: NOT инвертирует больше, чем кажется
Ещё одна ловушка — с NOT:
WHERE NOT department = 'IT' OR salary > 100000
Из-за приоритета это читается как:
WHERE (NOT department = 'IT') OR salary > 100000
То есть: «не-IT-шники» ПЛЮС все с зарплатой выше 100000 (в том числе из IT). Скорее всего имелось в виду:
WHERE NOT (department = 'IT' OR salary > 100000)
Что означает: «не-IT-шники с зарплатой не выше 100000». Полностью разная семантика.
Проверь себя: что вернёт WHERE a = 1 OR b = 2 AND c = 3? Как расставить скобки для (a=1 OR b=2) AND c=3?
Арифметика и сравнения
Арифметика вычисляется до логических операторов, поэтому такие выражения работают ожидаемо:
WHERE price * quantity > 10000 AND discount < 0.2
Сначала price * quantity (арифметика), затем > 10000 (сравнение), затем AND.
Но скобки всё равно полезны для наглядности:
WHERE (price * quantity > 10000) AND (discount < 0.2)
Явный смысл: «суммарная стоимость больше 10000 И скидка меньше 20%».
Скобки как документация
Скобки выполняют двойную роль: они управляют вычислением И служат документацией намерений. Читатель запроса не обязан держать в голове таблицу приоритетов. Скобки говорят явно: «эти условия — одна группа».
Сравните два записи одного и того же логического условия:
-- Без скобок (требует знания приоритетов)
WHERE status = 'active' AND age >= 18 OR status = 'pending' AND age >= 16
-- Со скобками (намерение очевидно)
WHERE (status = 'active' AND age >= 18)
OR (status = 'pending' AND age >= 16)
Второй вариант однозначно читается как: «либо активные совершеннолетние, либо ожидающие одобрения с 16 лет». Первый требует применения правила приоритета в голове.
Когда скобки не нужны
Если условие содержит только AND или только OR (без смешивания), скобки добавляют визуальный шум без пользы:
-- Только AND — скобки не нужны
WHERE department = 'IT' AND salary > 50000 AND hire_year > 2020
-- Только OR — скобки тоже лишние
WHERE status = 'active' OR status = 'pending' OR status = 'trial'
Здесь нет неоднозначности — приоритет одинаков для всех операторов, порядок вычисления очевиден.
Скобки становятся необходимыми при смешивании AND и OR в одном условии.
Вложенные скобки
Скобки можно вкладывать на любую глубину:
WHERE (department = 'IT' AND (salary > 80000 OR experience > 5))
OR (department = 'HR' AND salary > 60000)
Вычисление: сначала самые внутренние скобки (salary > 80000 OR experience > 5), затем AND department = 'IT', затем OR (department = 'HR' AND salary > 60000).
Это сложное условие, но со скобками его можно прочитать последовательно. Без скобок такое условие было бы почти нечитаемым.
Практика: найдите ошибку
Задача: найти активных клиентов из Москвы или Санкт-Петербурга. Разработчик написал:
SELECT name, city, status
FROM customers
WHERE city = 'Москва' OR city = 'Санкт-Петербург' AND status = 'active';
Что здесь не так? Из-за приоритета AND это читается как:
WHERE city = 'Москва' OR (city = 'Санкт-Петербург' AND status = 'active')
Результат: все клиенты из Москвы (независимо от статуса!) плюс активные из Санкт-Петербурга. Москвичи без статуса 'active' тоже попадут в результат — что является ошибкой.
Правильный запрос:
SELECT name, city, status
FROM customers
WHERE (city = 'Москва' OR city = 'Санкт-Петербург')
AND status = 'active';
Это вернёт только активных клиентов из обоих городов.
Трассировка: пошаговое вычисление сложного условия
Разберём сложное условие пошагово, как это делает СУБД:
Условие: a = 1 OR b = 2 AND c = 3 AND d = 4
Шаг 1 — находим все AND (высший приоритет):
b = 2 AND c = 3→ группа Bгруппа B AND d = 4→ группа C
Шаг 2 — применяем OR:
a = 1 OR группа C
Итоговая логика: a = 1 OR ((b = 2 AND c = 3) AND d = 4)
Если вы хотели (a=1 OR b=2) AND c=3 AND d=4 — без скобок это невозможно, нужно написать явно:
WHERE (a = 1 OR b = 2) AND c = 3 AND d = 4
Практические правила для команды
Если вы работаете в команде над одной кодовой базой, стоит выработать соглашение о скобках. Два разумных подхода:
Консервативный: всегда ставить скобки при смешивании AND и OR, даже если они технически не нужны по приоритету.
Минималистичный: скобки только там, где они меняют порядок вычисления (не где он совпадает с приоритетом).
Оба подхода рабочие. Важно — последовательность. «Иногда скобки, иногда нет» — хуже обоих вариантов, потому что читатель не знает, намеренно ли они отсутствуют.
Проверка через упрощённые подстановки
Хороший способ убедиться, что логика правильная — подставить конкретные значения и проверить, совпадает ли результат с ожидаемым.
Условие: WHERE status = 'active' OR role = 'admin' AND verified = true
Тест 1: status='inactive', role='admin', verified=true
status='active'→ FALSErole='admin' AND verified=true→ TRUE AND TRUE → TRUE- FALSE OR TRUE → TRUE ← попадает в результат
Вопрос: хотели ли мы, чтобы неактивные администраторы попадали в результат? Если нет — нужны скобки: (status='active' OR role='admin') AND verified=true.
Такая проверка с «граничными» тестовыми данными помогает поймать логические ошибки до того, как они попадут в продакшн.
Краткий итог
- Приоритет логических операторов:
NOT>AND>OR ANDвычисляется доOR— это главное правило для условийWHERE- При смешивании
ANDиORвсегда используйте скобки - Скобки не только управляют вычислением, но и документируют намерение
- Проверяйте сложные условия подстановкой граничных значений
- При только
ANDили толькоORскобки добавляют шум — их можно не ставить
Что дальше
Финальный урок этого модуля — практика с типичными ошибками в условиях WHERE. Вы увидите реальные примеры запросов с ошибками и научитесь их находить и исправлять. Это закрепит всё, что мы изучили в модуле 3.