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

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

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

Проблема 1: Ошибки при использовании ЛЕВОГО СОЕДИНЕНИЯ

Разберем классическую ошибку. Когда мы используем ЛЕВОЕ СОЕДИНЕНИЕ, мы ожидаем, что в результат попадут все записи из левой таблицы, даже если для них нет соответствия в правой. Однако, если добавить условие по полям правой таблицы в блок ГДЕ, соединение фактически превращается во ВНУТРЕННЕЕ.

Выясним причину: если в блоке ГДЕ указано условие на поле из присоединенной таблицы (например, ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.ДокОснование ССЫЛКА Документ.Маршрут), то для всех строк, где подготовки не было, значение поля будет NULL. Проверка на ссылку для NULL вернет ложь, и строка будет исключена из результата.

Рассмотрим правильный подход к написанию такого соединения:


ИЗ Документ.РСУ_РасходныйОрдер.ТЧОтгруженныеТМЦ КАК РСУ_РасходныйОрдерТЧОтгруженныеТМЦ
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке КАК ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке
ПО РСУ_РасходныйОрдерТЧОтгруженныеТМЦ.Ссылка.ПС_ДокМаршрут = ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.ДокОснование
И (ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.ДокОснование ССЫЛКА Документ.Маршрут)

Важно: все фильтры по правой таблице должны находиться внутри условия связи ПО. Это гарантирует, что записи из левой таблицы (расходные ордера) не пропадут, если подготовка еще не выполнена.

Проблема 2: Пустые табличные части документов

В процессе отладки часто выясняется, что запрос к табличной части документа (например, ТЧОтгруженныеТМЦ) возвращает пустой результат, хотя в интерфейсе данные видны. Проанализируем ситуацию: если запрос вида ВЫБРАТЬ * ИЗ Документ.ИмяДокумента.ИмяТЧ ГДЕ Ссылка = &Ссылка возвращает пустоту, значит, данные в этой конкретной табличной части физически отсутствуют в базе.

В некоторых конфигурациях данные могут отображаться в форме программно (из других регистров) или документ может иметь нулевые остатки. В таком случае решение — брать данные из первичного документа, например, из Документ.ПеремещениеТМЦ.ТЧ, связывая его с расходным ордером по ссылке в шапке.

Проблема 3: Некорректная группировка и суммирование количества

Когда мы соединяем табличную часть перемещения с другими таблицами, строки могут дублироваться. Если просто добавить поле Кол в СГРУППИРОВАТЬ ПО, мы получим некорректные итоги. Рассмотрим, как правильно агрегировать данные:

  1. Выбираем номенклатуру и количество из первичного документа.
  2. Используем функцию СУММА() для числовых полей.
  3. Группируем по всем остальным полям.

Пример правильной группировки для получения данных по перемещению:


ВЫБРАТЬ
    ПеремещениеТМЦТЧ.Номенклатура КАК Номенклатура,
    СУММА(ПеремещениеТМЦТЧ.Кол) КАК Кол,
    ПеремещениеТМЦТЧ.Ссылка.Автор КАК АвторПеремещения,
    ПеремещениеТМЦТЧ.Ссылка КАК Перемещение
ПОМЕСТИТЬ Номперем
ИЗ
    Документ.ПеремещениеТМЦ.ТЧ КАК ПеремещениеТМЦТЧ
ГДЕ
    ПеремещениеТМЦТЧ.Ссылка.Проведен
    И НЕ ПеремещениеТМЦТЧ.Ссылка.ПометкаУдаления
СГРУППИРОВАТЬ ПО
    ПеремещениеТМЦТЧ.Номенклатура,
    ПеремещениеТМЦТЧ.Ссылка,
    ПеремещениеТМЦТЧ.Ссылка.Автор;

Проблема 4: Дублирование строк из-за нескольких авторов подготовки

Ситуация: один товар в рамках одного маршрута могли готовить разные сотрудники. Если в регистре сведений ПодготовкаКОтгрузке записи делаются без детализации до номенклатуры (только по документу-основанию), то при соединении с табличной частью товаров каждая строка товара размножится на количество авторов подготовки.

Разберем варианты решения этой проблемы:

Вариант А: Использование МАКСИМУМ или МИНИМУМ. Если нам не принципиально видеть всех авторов, а достаточно одного (например, последнего), мы можем предварительно сгруппировать данные регистра во временной таблице:


ВЫБРАТЬ
    ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.ДокОснование КАК МаршрутПодготовка,
    МАКСИМУМ(ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.Автор) КАК АвторПодготовка
ПОМЕСТИТЬ Подготовка
ИЗ
    РегистрСведений.ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке КАК ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке
СГРУППИРОВАТЬ ПО
    ПС_ОтсканированныеУпаковкиПодготовкаКОтгрузке.ДокОснование;

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

Итоговый алгоритм построения стабильного запроса

Проанализируем шаги для создания надежного отчета в СКД:

  1. Подготовка данных о перемещении: создаем временную таблицу с номенклатурой и сгруппированным количеством.
  2. Подготовка данных о маршрутах и подготовке: собираем данные из регистра сведений, исключая дубли (если это необходимо для логики отчета).
  3. Сборка финальной таблицы: соединяем данные, начиная с основной сущности (например, расходного ордера).
  4. Использование параметров: обязательно проверяем условия по датам (&ДатаНач, &ДатаКон) и пометкам удаления.

Посмотрим на пример финальной структуры запроса, объединяющего эти принципы:


ВЫБРАТЬ
    РСУ_РасходныйОрдер.ПС_ДокМаршрут КАК МаршрутРасход,
    РСУ_РасходныйОрдер.Автор КАК АвторРасход,
    РСУ_РасходныйОрдер.ДокРасход КАК ПеремещениеРасход,
    Номперем.Номенклатура,
    Номперем.Кол,
    Подготовка.АвторПодготовка
ИЗ
    Номперем КАК Номперем
ЛЕВОЕ СОЕДИНЕНИЕ Документ.РСУ_РасходныйОрдер КАК РСУ_РасходныйОрдер
    ПО Номперем.Перемещение = РСУ_РасходныйОрдер.ДокРасход
ЛЕВОЕ СОЕДИНЕНИЕ Подготовка КАК Подготовка
    ПО РСУ_РасходныйОрдер.ПС_ДокМаршрут = Подготовка.МаршрутПодготовка
ГДЕ
    НЕ РСУ_РасходныйОрдер.ПометкаУдаления
    И РСУ_РасходныйОрдер.Проведен
    И РСУ_РасходныйОрдер.Дата МЕЖДУ &ДатаНач И &ДатаКон;

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

← На главную