Какой результат даст фильтр, в котором без скобок смешаны AND и OR, и какое правило определяет его разбор?

Какой результат даст фильтр, в котором без скобок смешаны AND и OR, и какое правило определяет его разбор?

Проходите собеседования с ИИ помощником Hintsage

Краткий ответ

В SQL оператор AND обычно имеет более высокий приоритет, чем OR, поэтому выражение без скобок сначала группируется по AND. Фильтр A AND B OR C интерпретируется как (A AND B) OR C, а не как A AND (B OR C).

Исторический контекст

SQL использует логические предикаты, чтобы описывать условия отбора строк в декларативной форме. При объединении нескольких условий возникла необходимость однозначно определить их смысл без обязательной расстановки скобок.

Для этого применяются правила приоритета логических операторов, знакомые по формальной логике и языкам программирования. Однако скобки остаются предпочтительным способом явно зафиксировать бизнес-правило и защитить запрос от неверного прочтения.

Постановка проблемы

Рассмотрим условие: активный пользователь должен иметь роль администратора или менеджера. Если записать его без скобок, можно случайно разрешить доступ любому менеджеру, даже неактивному.

Такая ошибка опасна тем, что запрос синтаксически корректен и возвращает правдоподобные данные. Она может привести к неверным отчётам, массовому изменению строк при UPDATE или удалению лишних записей при DELETE.

Подробное решение

Приоритет операторов обычно располагается так: сначала выполняется NOT, затем AND, затем OR. Поэтому SQL разбирает условие A AND B OR C как (A AND B) OR C.

SELECT user_id FROM users WHERE is_active = TRUE AND role = 'admin' OR role = 'manager';

В этом примере будут выбраны все активные администраторы и все менеджеры независимо от значения is_active. Если требуются только активные пользователи с одной из двух ролей, условие нужно явно сгруппировать: is_active = TRUE AND (role = 'admin' OR role = 'manager').

Скобки не только меняют порядок вычисления, но и делают намерение автора очевидным. Это особенно важно в условиях с несколькими уровнями AND и OR, при ревью и последующем изменении запроса.

Логика также учитывает значение UNKNOWN, возникающее при сравнении с NULL. Скобки не устраняют трёхзначную логику, но позволяют точно определить, как результаты TRUE, FALSE и UNKNOWN объединяются операторами.

Для надёжности нельзя полагаться только на визуальное форматирование строк или на предполагаемый порядок чтения. В сложных предикатах следует использовать скобки даже тогда, когда результат формально совпадает с естественным приоритетом операторов.

Ситуация из практики

В отчёте требовалось выбрать заказы, которые принадлежат активным клиентам и имеют статус «новый» или «повторный». Разработчик написал условие без скобок, из-за чего все заказы со статусом «повторный» попали в отчёт, включая заказы неактивных клиентов.

Рассматривались два варианта. Первый — оставить выражение без скобок, полагаясь на стандартный приоритет; плюс этого подхода только в краткости, а минус — высокий риск неверной интерпретации. Второй — явно сгруппировать альтернативные статусы; он немного длиннее, зато однозначен при проверке и изменении.

Выбрали второй вариант и добавили тесты для четырёх комбинаций: активный новый, активный повторный, неактивный новый и неактивный повторный клиент. В результате в отчёт попали только две требуемые категории, а регрессионные тесты стали фиксировать бизнес-правило.

Что кандидаты часто упускают

  1. Что изменится, если поменять местами AND и OR в условии?

    Изменится структура логического выражения, а значит, и набор строк. (A AND B) OR C пропускает все строки, удовлетворяющие C, тогда как A AND (B OR C) пропускает только строки, удовлетворяющие A и хотя бы одному из условий B или C. Эти выражения эквивалентны лишь в отдельных частных случаях.

  2. Достаточно ли переносить AND и OR на разные строки, чтобы изменить приоритет?

    Нет. Перевод строки, пробелы и форматирование не влияют на синтаксический разбор SQL. Приоритет определяется операторами и скобками, поэтому для изменения логики нужны явные круглые скобки.

  3. Как NULL влияет на результат составного условия?

    Сравнение значения с NULL обычно даёт UNKNOWN, а не TRUE или FALSE. Например, A AND UNKNOWN становится FALSE, если A равно FALSE, и UNKNOWN в остальных случаях; A OR UNKNOWN становится TRUE, если A равно TRUE, и UNKNOWN в остальных случаях. В секции WHERE сохраняются только строки, для которых всё условие имеет результат TRUE, поэтому UNKNOWN не проходит фильтрацию.