Как соединить данные регистра бухгалтерии и регистра накопления в отчете СКД без дублирования сумм

Программист 1С v8.3 (Управляемые формы) Бухгалтерский учет IT и автоматизация бизнеса
← На главную

При разработке сложных отчетов по заработной плате в системе 1С:Предприятие часто возникает необходимость объединить данные из разных источников: например, остатки и обороты по счетам из регистра бухгалтерии и данные по взносам из регистра накопления. Основная сложность здесь заключается в разной детализации данных, что приводит к «размножению» строк и некорректным итогам. Разберем по шагам, как решить эту задачу с помощью Системы компоновки данных (СКД).

Проблема 1: Дублирование данных при соединении (Cartesian Product)

Когда мы пытаемся соединить в одном запросе ЛЕВЫМ СОЕДИНЕНИЕМ регистр бухгалтерии (где есть субконто «Виды начислений») и регистр накопления (где есть измерение «Виды соцфонда»), система создает комбинацию каждой строки из первой таблицы с каждой строкой из второй для одного и того же сотрудника. Если у сотрудника 3 вида начисления и 2 вида соцфонда, вместо 5 строк мы можем получить 6 (3 * 2), а суммы начислений удвоятся.

Рассмотрим решение через предварительную свертку данных:

Самый надежный способ избежать дублирования в рамках одного запроса — это использование временных таблиц. Сначала мы должны «схлопнуть» данные по каждому регистру до общего измерения (в нашем случае — «Сотрудник»), а уже затем соединять эти результаты. Проанализируем пример логики запроса:


// Помещаем данные бухгалтерии во временную таблицу
ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.Сотрудник КАК Сотрудник,
    СУММА(ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстатокДт) КАК НачОст,
    СУММА(ХозрасчетныйОстаткиИОбороты.СуммаОборотДт) КАК ОборотНачисления,
    СУММА(ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт) КАК КонОст
ПОМЕСТИТЬ ВТ_Зарплата
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет = &СчетЗП, , ) КАК ХозрасчетныйОстаткиИОбороты
СГРУППИРОВАТЬ ПО
    ХозрасчетныйОстаткиИОбороты.Сотрудник;

// Помещаем данные соцфонда во временную таблицу
ВЫБРАТЬ
    СоцфондОбороты.Сотрудник КАК Сотрудник,
    СУММА(СоцфондОбороты.СуммаОборот) КАК СуммаСоцфонд
ПОМЕСТИТЬ ВТ_Соцфонд
ИЗ
    РегистрНакопления.Соцфонд.Обороты(&НачалоПериода, &КонецПериода, , ) КАК СоцфондОбороты
СГРУППИРОВАТЬ ПО
    СоцфондОбороты.Сотрудник;

После этого мы соединяем ВТ_Зарплата и ВТ_Соцфонд по полю Сотрудник. Теперь на каждого сотрудника будет приходиться строго одна строка, и суммы не «размножатся».

Проблема 2: Сохранение детальных оборотов в колонках

Автор темы столкнулся с тем, что ему нужно вывести обороты в разрезе видов начислений и видов соцфонда в разных колонках. Если мы свернем данные до сотрудника, мы потеряем эту аналитику. Здесь на помощь приходит механизм Связи наборов данных в СКД.

Разберем алгоритм настройки через два набора данных:

  1. Создаем НаборДанных1: Запрос к регистру бухгалтерии. В нем выбираем сотрудника, вид начисления и суммы.
  2. Создаем НаборДанных2: Запрос к регистру накопления. Выбираем сотрудника, вид соцфонда и суммы.
  3. Настраиваем связи: На вкладке «Связи наборов данных» указываем, что НаборДанных1 является источником связи, а НаборДанных2 — приемником. Условие связи: Сотрудник = Сотрудник.

Важный нюанс: Чтобы данные не дублировались при выводе детальных записей, в СКД лучше использовать тип группировки «Таблица». В строках мы указываем сотрудника, а в колонках создаем две параллельные группы: одну для «Видов начислений», другую для «Видов соцфонда». СКД сама сопоставит данные по сотруднику и выведет их корректно.

Проблема 3: Пропадание остатков при отборе по оборотному субконто

Выясним причину, почему при установке отбора по Виду начисления пропадают начальные и конечные остатки. В плане счетов 1С субконто может быть помечено как «Только обороты». Это означает, что в базе данных остатки в разрезе этого субконто не хранятся — они хранятся только в целом по счету и по сотруднику.

Когда вы накладываете отбор ГДЕ ВидНачисления = &Значение, система отсекает все записи, где поле ВидНачисления не заполнено. А в виртуальных таблицах остатков для записей, отражающих остаток по счету, это поле всегда пустое (NULL). В результате остатки «вымываются» из отчета.

Рассмотрим решение через экранирование отборов (фигурные скобки):

Для того чтобы отбор применялся только к оборотам, но не влиял на выборку остатков по сотруднику, необходимо использовать расширение языка запросов СКД. Проанализируем пример оформления условия в тексте запроса:


ВЫБРАТЬ
    ХозрасчетныйОстаткиИОбороты.Сотрудник КАК Сотрудник,
    ХозрасчетныйОстаткиИОбороты.Субконто2 КАК ВидНачисления,
    ХозрасчетныйОстаткиИОбороты.СуммаНачальныйОстатокДт КАК НачОст,
    ХозрасчетныйОстаткиИОбороты.СуммаОборотДт КАК Оборот,
    ХозрасчетныйОстаткиИОбороты.СуммаКонечныйОстатокДт КАК КонОст
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, , , Счет = &СчетЗП, , ) КАК ХозрасчетныйОстаткиИОбороты
ГДЕ
    // Обычное условие отсечет остатки
    // ВидНачисления = &ВидНачисления
    
    // Правильное условие для СКД:
    {ГДЕ ХозрасчетныйОстаткиИОбороты.Субконто2.* КАК ВидНачисления}

Использование конструкции {} позволяет СКД интеллектуально управлять запросом. Если пользователь не выбрал конкретный вид начисления в настройках, это условие вообще не попадет в итоговый SQL-запрос. Если же пользователь установит отбор, СКД применит его так, чтобы не нарушить логику получения остатков (если правильно настроены роли полей).

Альтернативный подход: Использование «ОБЪЕДИНИТЬ ВСЕ»

В профессиональной среде 1С-разработчиков часто считается «золотым стандартом» использование объединения вместо соединений для построения сложных отчетов. Это гарантирует отсутствие дублей и высокую производительность.

Посмотрим, как это работает:

  1. В первом запросе выбираем данные из регистра бухгалтерии. Поля соцфонда оставляем пустыми (0 или NULL).
  2. Через ОБЪЕДИНИТЬ ВСЕ добавляем второй запрос к регистру накопления. Здесь поля зарплаты оставляем пустыми, а поля соцфонда заполняем данными.
  3. В настройках СКД добавляем группировку по полю Сотрудник.

Пример структуры запроса:


ВЫБРАТЬ
    Зарплата.Сотрудник КАК Сотрудник,
    Зарплата.Субконто2 КАК Аналитика,
    Зарплата.СуммаНачальныйОстатокДт КАК НачОст,
    Зарплата.СуммаОборотДт КАК СуммаЗарплаты,
    0 КАК СуммаСоцфонд
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ОстаткиИОбороты(...) КАК Зарплата

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ
    Соцфонд.Сотрудник,
    Соцфонд.ВидСоцфонда,
    0,
    0,
    Соцфонд.СуммаОборот
ИЗ
    РегистрНакопления.Соцфонд.Обороты(...) КАК Соцфонд

В этом случае СКД самостоятельно «схлопнет» данные по сотруднику в одну строку. Суммы начислений и соцфонда окажутся в разных ресурсах, и вы сможете легко вывести их в одну таблицу без риска получить неверные итоги из-за умножения строк.

Настройка ресурсов и ролей полей

Для корректной работы остатков крайне важно правильно настроить вкладку «Набор данных» в конструкторе СКД. Проверьте следующие параметры для полей остатков:

Соблюдение этих правил позволит вам создать мощный и гибкий отчет, который будет корректно работать даже при сложных пользовательских отборах и больших объемах данных.

← На главную