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