При разработке сложных отчетов или документов, связанных с начислением заработной платы и ее отражением в бухгалтерском учете, часто возникает задача: выбрать данные по общему фильтру (например, по конкретному проекту), но при этом включить в выборку определенных сотрудников, чьи данные учитываются по иным правилам. В этой статье мы разберем, как правильно составить запрос, избежать ловушек с приоритетами логических операций и что делать, если запрос визуально правильный, но не возвращает ожидаемые строки.
Рассмотрим ситуацию: у нас есть запрос, который собирает данные из трех источников: РегистрРасчета.Начисления, РегистрСведений.БухучетРаспределениеОсновногоЗаработка и РегистрНакопления.БухучетНачисленияУдержанияПоСотрудникам. Основная цель — получить отработанные часы и суммы, распределенные по статьям финансирования и способам отражения.
Проблема заключается в блоке фильтрации ГДЕ. По умолчанию запрос выбирает всех сотрудников по одному конкретному способу отражения (параметр &Способ). Однако нам нужно добавить в этот же список еще одного сотрудника (с кодом "ПА2"), у которого способ отражения отличается и содержит в названии подстроку "Способ2".
Первоначальный вариант условия с использованием конструкции ВЫБОР выглядел так:
ГДЕ
ВЫБОР
КОГДА БухучетНачисленияУдержанияПоСотрудникам.Сотрудник = &Сотрудник ТОГДА
БухучетНачисленияУдержанияПоСотрудникам.СпособОтраженияЗарплатыВБухучете.Наименование ПОДОБНО "%Способ2%"
ИНАЧЕ
БухучетНачисленияУдержанияПоСотрудникам.СпособОтраженияЗарплатыВБухучете = &Способ
КОНЕЦ
И БухучетНачисленияУдержанияПоСотрудникам.Период МЕЖДУ &НачПериода И &КонПериода
На первый взгляд логика верна, но такой подход может не сработать из-за особенностей обработки NULL или неявных приоритетов. Разберем более надежные способы реализации этой логики.
Проанализируем альтернативный подход. Вместо громоздкой конструкции ВЫБОР в секции ГДЕ, эффективнее использовать сочетание операторов И и ИЛИ. Важно помнить, что в языке запросов 1С (как и в SQL) оператор И имеет более высокий приоритет, чем ИЛИ. Если не использовать скобки, запрос выдаст неверный результат или «размножит» строки.
Рассмотрим правильную структуру условия:
ГДЕ
(
(БухучетНачисленияУдержанияПоСотрудникам.Сотрудник = &Сотрудник
И БухучетНачисленияУдержанияПоСотрудникам.СпособОтраженияЗарплатыВБухучете.Наименование ПОДОБНО "%Способ2%")
ИЛИ
(БухучетНачисленияУдержанияПоСотрудникам.СпособОтраженияЗарплатыВБухучете = &Способ)
)
И БухучетНачисленияУдержанияПоСотрудникам.Период МЕЖДУ &НачПериода И &КонПериода
И БухучетНачисленияУдержанияПоСотрудникам.НачислениеУдержание.ВклВРаспределениеПЭО
В этом примере мы четко разделяем два сценария:
Обе группы условий объединяются общими фильтрами по периоду и признаку включения в распределение.
Часто программисты сталкиваются с тем, что код написан верно, но сотрудник "ПА2" все равно не попадает в выборку. Проанализируем возможные причины:
1. Особенности поиска по строке. Оператор ПОДОБНО "%Текст%" чувствителен к пробелам и невидимым символам. Если в наименовании способа отражения написано "Способ 2" (с пробелом), а вы ищете "%Способ2%", запись не будет найдена. Кроме того, использование процентов в начале строки "%..." отключает использование индексов СУБД, что замедляет запрос.
2. Расхождение данных в регистрах. В конфигурациях Зарплата и Управление Персоналом (ЗУП) 3.1 данные в регистр накопления БухучетНачисленияУдержанияПоСотрудникам записываются в момент проведения документов начисления (например, "Начисление зарплаты и взносов"). Если вы сначала изменили способ отражения в карточке сотрудника или в настройках штатного расписания, а документ начисления не перепровели, в регистре останутся старые данные.
Рекомендация: Всегда проверяйте данные напрямую через "Функции для технического специалиста" в соответствующем регистре, чтобы убедиться, какой именно способ отражения зафиксирован в движениях документа.
В исходном примере код сотрудника ("ПА2") и текст способа отражения прописаны жестко. С точки зрения качественной разработки, это плохая практика. Если завтра код сотрудника изменится или появится второй такой человек, придется снова лезть в код. Проанализируем, как сделать решение универсальным:
// Вместо НайтиПоКоду лучше использовать ссылку из настроек или передавать список
Запрос.УстановитьПараметр("Сотрудник", Справочники.Сотрудники.НайтиПоКоду("ПА2"));
Запрос.УстановитьПараметр("Способ", Объект.Проект);
// Если нужен поиск по строке, передавайте её целиком как параметр
Запрос.УстановитьПараметр("СтрокаПоиска", "%Способ2%");
В самом запросе используйте ПОДОБНО &СтрокаПоиска. Но еще лучше передавать конкретную ссылку на элемент справочника СпособыОтраженияЗарплатыВБухучете.
Если список «особых» сотрудников велик, условия в блоке ГДЕ становятся нечитаемыми. Разберем профессиональный метод решения через временные таблицы (ВТ).
ВТ_СписокИсключений, куда помещаем пары "Сотрудник" — "НужныйСпособ".ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы с этой ВТ.ГДЕ прописываем логику: если сотрудник есть в ВТ, проверяем соответствие его спец. способу, если нет — используем стандартный способ.Такой подход значительно упрощает отладку и позволяет легко расширять логику исключений без переписывания сложных цепочек И/ИЛИ.
Выясним кратко основные моменты, которые помогут вам добавить сотрудника в исключение:
И и ИЛИ.Наименованию через ПОДОБНО, если есть возможность использовать прямую ссылку на объект.Применяя эти шаги, мы добьемся стабильной работы запроса и корректного формирования ФОТ в документах распределения затрат.