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