При написании сложных запросов в 1С:Предприятии разработчики часто сталкиваются с ситуацией, когда данные отфильтровываются совсем не так, как ожидалось. Особенно часто это происходит при попытке объединить несколько условий в блоке ГДЕ с помощью операторов И и ИЛИ. Давайте разберем, почему возникают такие «логические ловушки» и как правильно выстраивать условия, чтобы избежать ошибок.
В языке запросов 1С, как и в большинстве языков программирования, существует строгий приоритет выполнения операций. Если вы не используете скобки, система интерпретирует ваше выражение следующим образом:
НЕ.И.ИЛИ.Именно из-за того, что И имеет приоритет выше, чем ИЛИ, ваше сложное условие может «развалиться» на части. Фраза А ИЛИ Б И В будет воспринята интерпретатором как А ИЛИ (Б И В). Если логика вашей бизнес-задачи требовала объединить А и Б перед проверкой В, вы неизбежно получите некорректный результат.
Рассмотрим ситуацию, с которой столкнулся автор: в коде было условие, которое должно было проверять остатки по счетам аренды, но по факту фильтрация счетов игнорировалась. Изначальный код выглядел примерно так:
ГДЕ
(ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток < 0
ИЛИ ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток = 0
И ЗадолженностьПоставщиков.СуммаНачальныйОстаток <> 0
И НЕ ЗадолженностьПоставщиков.Счет В (&СчетаРасчетыПоАренде)
ИЛИ (ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток > 0
ИЛИ ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток = 0
И ЗадолженностьПоставщиков.СуммаНачальныйОстаток <> 0
И ЗадолженностьПоставщиков.Счет В (&СчетаРасчетыПоАренде)))
Проблема заключается в том, что из-за отсутствия явных скобок для группировки всех условий, выражение ВалютнаяСуммаНачальныйОстаток > 0 стало самостоятельным условием. Это значит, что любая запись с положительным остатком попадала в выборку автоматически, независимо от того, какой счет указан в поле Счет.
Чтобы гарантированно получить нужный результат, воспользуемся следующими рекомендациями:
Для исправления исходной проблемы, нам необходимо жестко сгруппировать условия для счетов аренды, чтобы проверка валютного остатка всегда происходила в связке с конкретным счетом:
ГДЕ
(...)
ИЛИ (
(ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток > 0
ИЛИ ЗадолженностьПоставщиков.ВалютнаяСуммаНачальныйОстаток = 0)
И ЗадолженностьПоставщиков.СуммаНачальныйОстаток <> 0
И ЗадолженностьПоставщиков.Счет В (&СчетаРасчетыПоАренде)
)
Как мы увидели при анализе темы, использование инструментов (например, консолей запросов с функциями форматирования) позволяет представить запрос в виде дерева логики. Когда запрос отформатирован правильно, вы сразу увидите, какие ветки стали «лишними» или «независимыми». Всегда приводите код к структурированному виду, где каждый оператор ИЛИ находится на отдельной строке, а вложенные условия выделены отступами. Это позволит сэкономить часы отладки при возникновении ошибок в расчетах.
Помните: в 1С приоритет оператора И выше приоритета ИЛИ. Исходя из этого правила, всегда проверяйте, не «оторвалось» ли ваше условие от основной логики запроса.