При создании отчетов в системе 1С:Предприятие часто возникает необходимость объединения данных из различных источников, таких как регистры сведений, справочники, документы. В частности, задача формирования отчета по начислениям сотрудников, который бы корректно обрабатывал уволенных работников и включал их кадровые данные, является достаточно распространенной. Рассмотрим подробно, как эффективно решить эту задачу, избегая распространенных ошибок, таких как пропуск сотрудников или показателей, а также несоответствие типов данных.
Изначально, вы можете столкнуться с проблемой, пытаясь использовать стандартный "Универсальный отчет" для решения этой задачи. Важно понимать, что "Универсальный отчет" обычно предназначен для работы с одним источником данных (одной таблицей, регистром, справочником). Если нам требуется объединить данные из нескольких таблиц, настроить сложные отборы или группировки, "Универсальный отчет" не сможет предоставить необходимую гибкость. В таких случаях нам потребуется создать собственный отчет, используя Систему компоновки данных (СКД) или напрямую написать запрос.
Первым шагом нам нужно получить информацию о дате увольнения сотрудников. В системе 1С:Зарплата и Управление Персоналом (ЗУП) или аналогичных конфигурациях для этого используются следующие регистры сведений:
РегистрСведений.ТекущиеКадровыеДанныеСотрудников: Этот регистр содержит актуальные кадровые данные по сотрудникам на текущий момент, включая дату увольнения, если сотрудник уволен. Он удобен для получения "среза последних" данных.РегистрСведений.КадроваяИсторияСотрудников: Этот регистр хранит историю всех кадровых событий (прием, перевод, увольнение). Если нам нужна полная история или специфические события, обращаемся к нему, часто используя срез последних по определенному виду события или по периоду.Предположим, наш основной источник данных — это РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних. Мы хотим добавить к нему дату увольнения. Для этого нам необходимо соединить (связать) эти таблицы в запросе.
Критически важно выбрать правильный тип соединения таблиц:
ВНУТРЕННЕЕ СОЕДИНЕНИЕ (INNER JOIN): При использовании внутреннего соединения в результат запроса попадут только те записи, для которых есть соответствие в обеих соединяемых таблицах по указанным полям. Это может привести к потере данных, если, например, для какого-то сотрудника нет записи в регистре кадровых данных, или, наоборот, нет записей о показателях, но есть кадровые данные.ЛЕВОЕ СОЕДИНЕНИЕ (LEFT JOIN): Левое соединение возвращает все записи из "левой" таблицы (той, что указана первой в операторе ИЗ) и совпадающие записи из "правой" таблицы. Если совпадений в "правой" таблице нет, поля из нее будут содержать значение NULL. Этот тип соединения предпочтителен, когда мы хотим сохранить все записи из основного источника данных, даже если для них нет связанных данных в другой таблице.В нашем случае, если основной источник данных — ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних, и мы хотим видеть всех сотрудников с их показателями, даже если они еще не уволены (и, соответственно, не имеют даты увольнения в регистре), или если по какой-то причине отсутствует запись в регистре кадровых данных, нам следует использовать ЛЕВОЕ СОЕДИНЕНИЕ.
Рассмотрим пример запроса, который объединяет значения периодических показателей с текущими кадровыми данными, используя ЛЕВОЕ СОЕДИНЕНИЕ, чтобы избежать потери сотрудников:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Период КАК Период,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация КАК Организация,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо КАК ФизическоеЛицо,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК Значение,
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения
ИЗ
РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних({(&КонецПериода)}) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо
Обратите внимание на условия соединения: мы связываем таблицы по полям Сотрудник, Организация (важно учитывать, что в ТекущиеКадровыеДанныеСотрудников это поле называется ГоловнаяОрганизация) и ФизическоеЛицо. Это обеспечивает точное соответствие записей.
После того как мы объединили данные, мы можем добавить отбор. Чтобы исключить уволенных сотрудников, мы используем поле ДатаУвольнения, которое теперь доступно в нашем запросе благодаря соединению. Если сотрудник не уволен, то поле ДатаУвольнения будет иметь значение NULL.
Для того чтобы в отчете остались только работающие сотрудники, мы можем добавить условие в секцию ГДЕ или в параметры отчета СКД:
ГДЕ
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ NULL
Если же, наоборот, нам нужны только уволенные сотрудники, условие будет выглядеть так:
ГДЕ
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ НЕ NULL
Или, для конкретного периода увольнения:
ГДЕ
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения МЕЖДУ &НачалоПериодаУвольнения И &КонецПериодаУвольнения
Проблема, когда в отчете отсутствуют некоторые сотрудники или их показатели (например, Компенсация расходов при дистанционной работе или Премия индивидуальная ежемесячная), является одной из самых частых при построении сложных отчетов. Рассмотрим основные причины и способы их устранения.
ВНУТРЕННЕЕ СОЕДИНЕНИЕ?Как мы уже выяснили, ВНУТРЕННЕЕ СОЕДИНЕНИЕ требует наличия соответствия в обеих таблицах. Если вы использовали ВНУТРЕННЕЕ СОЕДИНЕНИЕ, как в запросе из сообщения 17:
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо
...то причиной пропажи сотрудников является, скорее всего, отсутствие соответствующей записи в регистре ТекущиеКадровыеДанныеСотрудников по всем указанным условиям соединения для этих трех работников. Возможно, для них нет актуальных кадровых данных на указанную дату среза, или есть какие-то несоответствия в полях Организация/ГоловнаяОрганизация, ФизическоеЛицо. Использование ЛЕВОГО СОЕДИНЕНИЯ, как показано в предыдущем примере, является решением для включения всех сотрудников из основного источника.
Если у сотрудника не попадают определенные показатели (например, Компенсация расходов при дистанционной работе или Премия индивидуальная ежемесячная), даже если назначение планового начисления по ним есть, необходимо провести комплексную проверку. Разберем по шагам, что следует проанализировать:
Начисления).Назначение планового начисления, Кадровый перевод, Изменение плановых начислений, или же он может вводиться как разовый показатель через Данные для расчета зарплаты, Разовое начисление и т.д.СрезПоследних({(&КонецПериода)})). Если КонецПериода задан некорректно или слишком рано, вы можете не увидеть актуальные данные.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников обычно содержит плановые показатели, а фактические начисления будут в других регистрах (например, Начисления).Тщательная проверка этих пунктов позволит выявить причину отсутствия показателей.
Ошибка "Несоответствие типов" (или "Несоотвествие типов", как указано в сообщении 19) является одной из самых распространенных при работе с запросами в 1С. Она возникает, когда вы пытаетесь выполнить операцию (сравнение, присвоение, использование в функции) со значениями, которые имеют несовместимые типы данных (например, сравниваете число с датой, или ссылку на объект с пустой ссылкой).
Справочник.Сотрудники.Ссылка (тип Ссылка) с полем типа Строка или Число. Или соединение по полю Организация, когда в одной таблице это ссылка, а в другой – строка или NULL.{(&КонецПериода)}), и вы передаете в него значение, тип которого не соответствует ожидаемому (например, строку вместо даты).Рассмотрим запрос из сообщения 18, который вызвал ошибку "Несоответствие типов":
ВЫБРАТЬ РАЗРЕШЕННЫЕ
Сотрудники.Ссылка КАК Сотрудник,
КадроваяИсторияСотрудниковСрезПоследних.Организация КАК Организация,
КадроваяИсторияСотрудниковСрезПоследних.Подразделение КАК Подразделение,
КадроваяИсторияСотрудниковСрезПоследних.Должность КАК Должность,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК Значение,
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения
ИЗ
РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних КАК КадроваяИсторияСотрудниковСрезПоследних
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПРАВОЕ СОЕДИНЕНИЕ РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
ПО (ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка)
ПРАВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ПО (ТекущиеКадровыеДанныеСотрудников.Сотрудник = Сотрудники.Ссылка)
ПО КадроваяИсторияСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка И КадроваяИсторияСотрудниковСрезПоследних.ГоловнойСотрудник = Сотрудники.Ссылка
В этом запросе есть несколько потенциальных проблем:
ЛЕВОЕ и ПРАВОЕ СОЕДИНЕНИЕ: Смешивание ЛЕВОЕ и ПРАВОЕ СОЕДИНЕНИЕ может быть очень запутанным и приводить к неожиданным результатам, а также к ошибкам типов, если порядок выполнения соединений не тот, который вы предполагаете. Лучше всего придерживаться одной стратегии, например, всегда использовать ЛЕВОЕ СОЕДИНЕНИЕ, начиная с основной (самой полной) таблицы.ПО: Обратите внимание на последнюю строку с ПО КадроваяИсторияСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка И КадроваяИсторияСотрудниковСрезПоследних.ГоловнойСотрудник = Сотрудники.Ссылка. Она относится к РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних. Однако, если Справочник.Сотрудники был "левой" таблицей для КадроваяИсторияСотрудниковСрезПоследних, а затем к Справочник.Сотрудники присоединялись другие таблицы через ПРАВОЕ СОЕДИНЕНИЕ, связь может быть потеряна или некорректно установлена, вызывая ошибку типа.Сотрудники.Ссылка: Само по себе это правильно, если Сотрудник в регистрах является ссылкой на справочник Сотрудники. Но важно, чтобы это всегда было так.Давайте построим более надежный запрос, используя ЛЕВОЕ СОЕДИНЕНИЕ от основного регистра с показателями, чтобы получить всех сотрудников и их данные, даже если некоторые данные отсутствуют:
ВЫБРАТЬ РАЗРЕШЕННЫЕ
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Период КАК ПериодПоказателя,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник КАК Сотрудник,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация КАК ОрганизацияПоказателя,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель КАК Показатель,
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Значение КАК ЗначениеПоказателя,
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения КАК ДатаУвольнения,
Сотрудники.Наименование КАК НаименованиеСотрудника,
Сотрудники.Подразделение КАК ПодразделениеСотрудника,
Сотрудники.Должность КАК ДолжностьСотрудника,
КадроваяИсторияСотрудниковСрезПоследних.ВидСобытияКадровойИстории КАК ВидКадровогоСобытия
ИЗ
РегистрСведений.ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних({(&КонецПериода)}) КАК ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних
ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Сотрудники КАК Сотрудники
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = Сотрудники.Ссылка
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ТекущиеКадровыеДанныеСотрудников КАК ТекущиеКадровыеДанныеСотрудников
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = ТекущиеКадровыеДанныеСотрудников.Сотрудник
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = ТекущиеКадровыеДанныеСотрудников.ГоловнаяОрганизация
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.ФизическоеЛицо = ТекущиеКадровыеДанныеСотрудников.ФизическоеЛицо
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(
{(&КонецПериода)},
Сотрудник = ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник
И Организация = ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация
) КАК КадроваяИсторияСотрудниковСрезПоследних
ПО ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Сотрудник = КадроваяИсторияСотрудниковСрезПоследних.Сотрудник
И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Организация = КадроваяИсторияСотрудниковСрезПоследних.Организация
ГДЕ
// Пример отбора: только работающие сотрудники (не уволенные)
ТекущиеКадровыеДанныеСотрудников.ДатаУвольнения ЕСТЬ NULL
// Или другой отбор, если нужен. Например, только сотрудники с определенным показателем:
// И ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудниковСрезПоследних.Показатель = &ВыбранныйПоказатель
В этом запросе мы сделали следующее:
ЗначенияПериодическихПоказателейРасчетаЗарплатыСотрудников.СрезПоследних, что гарантирует наличие всех показателей, которые нас интересуют.Справочник.Сотрудники для получения общих данных о сотруднике (Наименование, Подразделение, Должность).РегистрСведений.ТекущиеКадровыеДанныеСотрудников для получения ДатаУвольнения, используя ЛЕВОЕ СОЕДИНЕНИЕ и подробные условия связи по Сотрудник, Организация (ГоловнаяОрганизация), ФизическоеЛицо. Это максимально снижает риск ошибки "Несоответствие типов", так как мы точно связываем поля одинакового типа.РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних для получения информации о последних кадровых событиях. Здесь важно правильно использовать параметры среза для этого регистра.ГДЕ для отбора по уволенным/работающим сотрудникам, используя поле ДатаУвольнения из присоединенного регистра.Такой подход обеспечивает максимальную надежность запроса и минимизирует вероятность ошибок "Несоответствие типов" или пропажи данных.
Для отладки запросов и проверки их работоспособности всегда используйте Консоль запросов. Она позволяет пошагово выполнять запрос, просматривать промежуточные результаты и оперативно выявлять ошибки.
Создание отчета по начислениям с учетом кадровых данных требует внимательного подхода к формированию запросов. Всегда начинайте с определения основного источника данных, а затем постепенно присоединяйте необходимые вспомогательные регистры и справочники, используя ЛЕВОЕ СОЕДИНЕНИЕ, чтобы сохранить максимальное количество данных из основного источника.
Помните, что "Универсальный отчет" не подходит для сложных сценариев, требующих объединения нескольких таблиц. В таких случаях мы рекомендуем создавать отчеты на базе Системы Компоновки Данных (СКД), которая предоставляет мощные инструменты для визуального конструирования запросов, отборов, группировок и макетов.
Если возникают ошибки "Несоответствие типов", тщательно проверяйте типы данных во всех полях, участвующих в условиях соединения и отбора. Пропажа данных чаще всего связана с неправильным типом соединения (использование ВНУТРЕННЕГО вместо ЛЕВОГО) или некорректными параметрами срезов. Последовательная отладка в Консоли запросов поможет быстро выявить и устранить проблему.