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