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