Мы, как разработчики 1С, нередко сталкиваемся с ситуацией, когда Система Компоновки Данных (СКД) в отчете не выводит все ожидаемые данные, особенно при использовании левого соединения. Кажется, что запрос составлен верно, в консоли запросов он возвращает полные данные, но при формировании отчета СКД мы видим только часть информации, чаще всего, только из левой таблицы. Давайте подробно разберем, почему возникает такая проблема и как мы можем ее решить.
Основная сложность заключается в том, что СКД активно оптимизирует запрос для повышения производительности. Эта оптимизация может привести к тому, что ваш исходный запрос будет изменен: некоторые поля или даже целые таблицы, участвующие в левом соединении, могут быть исключены из итогового запроса к базе данных, если СКД посчитает их "ненужными". Помимо этого, распространенной причиной являются кэшированные или устаревшие настройки самого отчета.
Первый и самый важный шаг в решении любой проблемы с СКД — это понять, какой SQL-запрос СКД на самом деле отправляет в базу данных. Это поможет нам выяснить, исключены ли из запроса необходимые нам поля или таблицы, или, возможно, изменились условия соединения.
Используем "Консоль запросов СКД". Это незаменимый инструмент для анализа запросов, которые генерирует СКД. Мы можем загрузить в него нашу схему компоновки данных, сформировать отчет с требуемыми настройками и затем просмотреть сгенерированный итоговый SQL-запрос. Это позволяет нам увидеть запрос именно в том виде, в котором он будет выполнен платформой.
Воспользуемся инструментами разработчика 1С. В режиме отладки мы можем установить точку останова непосредственно перед выполнением отчета СКД. Если отчет формируется программно, мы можем перехватить запрос, который генерирует СКД перед его отправкой в базу данных. Это дает нам прямой доступ к финальному запросу.
После получения итогового запроса, мы внимательно сравниваем его с нашим исходным запросом. На что следует обратить внимание:
ВЫБРАТЬ?ГДЕ дополнительных условий, которые могли бы неявно преобразовать левое соединение во внутреннее?Если в ходе диагностики мы обнаружили, что СКД "выбросила" необходимые нам поля из запроса, мы можем принудительно заставить ее включать их в итоговый запрос. Для этого существует специальный механизм.
Откроем конструктор запросов набора данных СКД.
Перейдем на вкладку "Компоновка данных". Здесь мы видим список всех полей, доступных в нашем запросе.
Для каждого поля, которое должно обязательно присутствовать в запросе, но не всегда выводится в отчете (особенно это касается полей из правой части левого соединения), установим флажок в колонке "Обязательная". Этот флаг явно указывает СКД, что данное поле не подлежит оптимизации и должно быть включено в итоговый запрос, даже если оно не используется в текущей настройке отчета (например, не выведено в колонках или не участвует в ресурсах).
Также важно помнить, что СКД может полностью удалить блоки запроса, заключенные в фигурные скобки (например, {ЛЕВОЕ СОЕДИНЕНИЕ ...}), если ни одно из полей присоединяемой таблицы не используется в отчете. Установка флага "Обязательная" для хотя бы одного поля из такого блока предотвратит его удаление.
Нередко проблема неполного вывода данных кроется не в запросе, а в некорректной настройке самого отчета СКД, его ресурсов, группировок или отборов. Проанализируем эти аспекты.
Ресурсы: Если данные из правой части соединения представляют собой числовые значения (например, Количество из табличной части документа), убедимся, что они правильно определены как ресурсы в СКД. Для них должна быть указана функция агрегации (например, СУММА(Количество), МАКСИМУМ(Количество) или МИНИМУМ(Количество)). Без агрегации СКД может не выводить их или выводить некорректно, особенно если в группировках нет соответствующих измерений.
Группировки: Если поля из правой части левого соединения должны выступать в качестве измерений, убедимся, что они участвуют в группировках отчета. Если такие поля не сгруппированы, их значения могут отображаться некорректно или быть невидимыми. Кроме того, в свойстве поля группировки подчиненного набора данных может быть установлен флажок "Игнорировать значения NULL". Если мы хотим видеть строки, где нет данных из связанного набора, нам следует снять этот флажок.
Отборы: Это один из наиболее коварных моментов при работе с левыми соединениями. Отбор, установленный на поле из правой части левого соединения, фактически может превратить его во внутреннее соединение. Рассмотрим пример:
ВЫБРАТЬ
ЛеваяТаблица.Поле1,
ПраваяТаблица.Поле2
ИЗ
ЛеваяТаблица КАК ЛТ
ЛЕВОЕ СОЕДИНЕНИЕ ПраваяТаблица КАК ПТ
ПО ЛТ.Ключ = ПТ.Ключ
ГДЕ
ПТ.НекийРеквизит = &Параметр
В этом случае, все строки из левой таблицы (ЛеваяТаблица), для которых нет соответствия в правой (ПраваяТаблица), будут иметь значение NULL для поля ПТ.НекийРеквизит. Условие ГДЕ ПТ.НекийРеквизит = &Параметр отсечет все эти строки, так как NULL не равно никакому значению параметра. Таким образом, отчет будет показывать только те строки, для которых нашлось соответствие в обеих таблицах, что эквивалентно внутреннему соединению. Если нам нужно сохранить все строки из левой таблицы, рассмотрите возможность применения отбора к параметрам функции получения остатков/оборотов, если это возможно, или используйте функцию ЕСТЬNULL() для поля в условии отбора, например: ГДЕ ЕСТЬNULL(ПТ.НекийРеквизит, &ЗначениеПоУмолчанию) = &Параметр.
Проанализируем ваш запрос из сообщения 8, который мы можем обобщить следующим образом:
ВЫБРАТЬ
// ... поля из ДанныеРН
ВложенныйЗапрос.Ссылка КАК Ссылка,
ВложенныйЗапрос.Количество КАК Количество,
ВложенныйЗапрос.Номенклатура КАК Номенклатура
ИЗ
РегистрНакопления.кф_ТоварыНаСкладахУУ.ОстаткиИОбороты(, , Авто, , ) КАК ДанныеРН
ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ
кф_КонвертерТоваровУУТовары.Ссылка КАК Ссылка,
кф_КонвертерТоваровУУТовары.Ссылка.СкладОтправитель КАК Склад,
кф_КонвертерТоваровУУТовары.Номенклатура КАК Номенклатура,
кф_КонвертерТоваровУУТовары.Количество КАК Количество
ИЗ
Документ.кф_КонвертерТоваровУУ.Товары КАК кф_КонвертерТоваровУУТовары
ГДЕ
НЕ кф_КонвертерТоваровУУТовары.Ссылка.Проведен
И НЕ кф_КонвертерТоваровУУТовары.Ссылка.ПометкаУдаления
СГРУППИРОВАТЬ ПО
кф_КонвертерТоваровУУТовары.Ссылка.СкладОтправитель,
кф_КонвертерТоваровУУТовары.Ссылка,
кф_КонвертерТоваровУУТовары.Номенклатура,
кф_КонвертерТоваровУУТовары.Количество
) КАК ВложенныйЗапрос
ПО ДанныеРН.Номенклатура = ВложенныйЗапрос.Номенклатура
И ДанныеРН.Склад = ВложенныйЗапрос.Склад
В этом запросе условие ГДЕ НЕ кф_КонвертерТоваровУУТовары.Ссылка.Проведен И НЕ кф_КонвертерТоваровУУТовары.Ссылка.ПометкаУдаления применяется внутри вложенного запроса. Это означает, что во ВложенныйЗапрос попадут только данные по непроведенным и неудаленным документам. Если ДанныеРН содержат информацию по проведенным документам, для которых нет соответствующих непроведенных документов в ВложенныйЗапрос, то левое соединение не найдет пару. В этом случае поля из ВложенныйЗапрос (такие как ВложенныйЗапрос.Количество) будут иметь значение NULL для этих строк. Такое поведение является корректным для левого соединения, но если вы ожидали увидеть "Цифры" (Количество) из табличной части для всех записей из регистра накопления, то данное условие в подзапросе может быть причиной их отсутствия. Убедитесь, что логика отбора в вашем вложенном запросе соответствует вашим бизнес-ожиданиям.
Как показала практика, одна из наиболее частых, но часто упускаемых из виду причин проблем с СКД — это кэширование старых настроек отчета. Если отчет ранее формировался с другими параметрами, эти настройки могли сохраниться и теперь мешают корректному отображению данных, даже если сам запрос уже изменен.
Сброс к стандартным настройкам. В пользовательском режиме откроем отчет. Обычно на форме отчета есть кнопка "Стандартные настройки" или ее можно найти в меню "Ещё -> Изменить вариант отчета -> Стандартные настройки" (точные названия могут варьироваться в зависимости от конфигурации и версии платформы). Нажмем ее, чтобы сбросить все пользовательские изменения и вернуть отчет к исходным настройкам, заложенным в макете СКД.
Удаление сохраненных вариантов отчета. Если сброс к стандартным настройкам не помог, возможно, пользовательские настройки отчета (сохраненные варианты) конфликтуют. Попробуем удалить все сохраненные варианты отчета для текущего пользователя или создать новый вариант отчета с нуля. Это гарантирует, что мы не используем устаревшие или поврежденные настройки.
Очистка кэша 1С. В крайних случаях, когда предыдущие шаги не дают результата, можно прибегнуть к очистке кэша 1С для текущей информационной базы. Это более радикальный шаг, который удаляет временные файлы и кэшированные данные платформы. Очистить кэш можно, удалив папки с числовыми названиями в каталогах, расположенных по путям, например: %LOCALAPPDATA%\1C\1Cv8\cache, %APPDATA%\1C\1Cv8\cache. После очистки кэша рекомендуется перезапустить 1С.
В некоторых сложных случаях, когда единый запрос с множеством соединений становится громоздким, трудноуправляемым или неэффективным, мы можем рассмотреть использование нескольких наборов данных в СКД. Этот подход позволяет более гибко контролировать получение и агрегацию данных.
Создадим первый набор данных для получения основных данных, например, из регистра накопления.
Создадим второй набор данных для получения дополнительных данных, например, из табличной части документа.
Настроим "Связи наборов данных" в СКД между этими двумя наборами. Важно понимать, что связи наборов данных в СКД по умолчанию реализуются как левое соединение. Мы указываем поля, по которым должны быть связаны наборы данных.
Этот подход может значительно улучшить читаемость схемы компоновки данных, дать нам более точный контроль над логикой агрегации и фильтрации для каждого набора, а также потенциально повысить производительность отчета, особенно при работе с большими объемами данных или когда данные необходимо получать из разных источников.
В заключение, при работе с СКД и левыми соединениями всегда помним о том, что СКД активно оптимизирует запрос. Тщательная диагностика с помощью консоли запросов СКД, внимательная проверка всех настроек отчета, ресурсов, группировок, отборов и, что очень важно, сброс пользовательских настроек, помогут нам успешно решить проблему неполного вывода данных и добиться желаемого результата в отчетах.