Почему отчет СКД пустой, хотя запрос в консоли 1С выдает верные данные?

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

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

Причина 1: СКД "оптимизирует" ваш запрос

Одной из самых частых причин является то, что СКД, стремясь к производительности, может "оптимизировать" или даже перестраивать исходный запрос, который вы ввели. Это означает, что запрос, который в итоге выполняет платформа, может существенно отличаться от вашего первоначального. СКД может исключать поля, которые, по ее мнению, не используются в настройках отчета, или изменять способ применения отборов и параметров.

  1. Исключение критичных полей. Если у вас есть поля, которые критичны для логики запроса (например, используются в агрегатных функциях типа КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ...), в условиях ВЫБОР КОГДА или для вычисления других показателей), но при этом вы не выводите их напрямую в отчет, СКД может посчитать их ненужными и удалить из генерируемого запроса. Это приводит к некорректным или пустым результатам.
  2. Решение: Пометка полей как "Обязательные". Чтобы избежать этого, нам необходимо в настройках набора данных СКД для таких полей установить флаг "Обязательное". Рассмотрим подробнее, как это сделать:
    1. Откройте схему компоновки данных.
    2. Перейдите на вкладку "Наборы данных".
    3. Выберите ваш набор данных (обычно это "Запрос").
    4. Перейдите на вкладку "Поля".
    5. Найдите поля, которые критичны для логики запроса, но не выводятся в отчет.
    6. Установите для них флаг в колонке "Обязательное".

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

Причина 2: Некорректная настройка и передача параметров

Даже если параметры корректно определены в вашем запросе, они должны быть правильно настроены в самой СКД. Неверная передача или отсутствие использования параметров — частый источник проблем.

  1. Настройка параметров в схеме СКД.

    Мы должны убедиться, что параметры, такие как ПериодС, ПериодПо и Контрагенты, правильно настроены на вкладке "Параметры" схемы компоновки данных.

    1. Откройте схему компоновки данных.
    2. Перейдите на вкладку "Параметры".
    3. Найдите ваши параметры (например, ПериодС, ПериодПо, Контрагенты).
    4. Убедитесь, что для каждого из них установлен флаг "Использование". Без этого флага СКД просто не будет применять эти параметры к запросу.
    5. Желательно также установить флаг "Включать в пользовательские настройки", чтобы пользователи могли изменять эти параметры при формировании отчета.
    6. Установите адекватные "Значения по умолчанию" для параметров, чтобы отчет мог быть сформирован без явного указания значений пользователем.
  2. Точность дат для виртуальных таблиц.

    При работе с виртуальными таблицами регистров накопления, такими как Обороты, критически важно правильно указывать границы периода. Дата окончания (&ПериодПо) должна включать данные до конца дня, то есть до 23:59:59. В противном случае данные за последний день периода могут быть не включены в отчет.

    Рекомендуем использовать функцию КОНЕЦДНЯ() для параметра ПериодПо. Это гарантирует, что все операции за последний день периода будут учтены. Давайте посмотрим на пример:

    
    // Пример кода на языке 1С для установки параметра ПериодПо
    ПараметрыДанных.Вставить("ПериодПо", КонецДня(ПараметрыФормы.ПериодПо));
    

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

    
    ИЗ
        РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
    
  3. Использование регистров вместо документов.

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

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

    
    ВЫБРАТЬ
        // Уровень 1 - Итоги
        ОбщееколичествоДней КАК КоличествоДнейСПродажами,
        ОбщееколичествоКлиентов КАК КоличествоКлиентов,
        "" КАК ДоляОтПродаж,
        ОбщаяВыручка КАК Выручка
    ИЗ
        (ВЫБРАТЬ
            КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Документ.Дата) КАК ОбщееколичествоДней,
            КОЛИЧЕСТВО(РАЗЛИЧНЫЕ ВЫБОР
                    КОГДА Продажи.Документ.РеальныйПолучатель <> НЕОПРЕДЕЛЕНО
                        ТОГДА Продажи.Документ.РеальныйПолучатель
                    ИНАЧЕ Продажи.Документ.Контрагент
                КОНЕЦ) КАК ОбщееколичествоКлиентов,
            СУММА(Продажи.Документ.СуммаДокумента) КАК ОбщаяВыручка
        ИЗ
            РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
        ГДЕ
            (&Контрагенты = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
                ИЛИ Продажи.Документ.Контрагент В (&Контрагенты)
                ИЛИ Продажи.Документ.Контрагент В ИЕРАРХИИ(&Контрагенты))
        ) КАК Итоги
            
    ОБЪЕДИНИТЬ ВСЕ
            
    ВЫБРАТЬ
        // Уровень 2 - Группы по дням
        ГруппыПоДням.КоличествоДнейСПродажами,
        ГруппыПоДням.КоличествоКлиентов,
        ГруппыПоДням.ДоляВВыручке,
        ГруппыПоДням.ВыручкаПоГруппе
    ИЗ
        (ВЫБРАТЬ
            КлиентыСКоличествомДней.КоличествоДней КАК КоличествоДнейСПродажами,
            КОЛИЧЕСТВО(КлиентыСКоличествомДней.Клиент) КАК КоличествоКлиентов,
            СУММА(КлиентыСКоличествомДней.СуммаПоКлиенту) КАК ВыручкаПоГруппе,
            Итоги.ОбщаяВыручка,
            ВЫБОР
                КОГДА Итоги.ОбщаяВыручка > 0
                    ТОГДА СУММА(КлиентыСКоличествомДней.СуммаПоКлиенту) / Итоги.ОбщаяВыручка * 100
                ИНАЧЕ 0
            КОНЕЦ КАК ДоляВВыручке
        ИЗ
            (ВЫБРАТЬ
                ВЫБОР
                    КОГДА Продажи.Документ.РеальныйПолучатель <> НЕОПРЕДЕЛЕНО
                        ТОГДА Продажи.Документ.РеальныйПолучатель
                    ИНАЧЕ Продажи.Документ.Контрагент
                КОНЕЦ КАК Клиент,
                КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Продажи.Документ.Дата) КАК КоличествоДней,
                СУММА(Продажи.Документ.СуммаДокумента) КАК СуммаПоКлиенту
            ИЗ
                РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
            ГДЕ
                (&Контрагенты = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
                    ИЛИ Продажи.Документ.Контрагент В (&Контрагенты)
                    ИЛИ Продажи.Документ.Контрагент В ИЕРАРХИИ(&Контрагенты))
            СГРУППИРОВАТЬ ПО
                ВЫБОР
                    КОГДА Продажи.Документ.РеальныйПолучатель <> НЕОПРЕДЕЛЕНО
                        ТОГДА Продажи.Документ.РеальныйПолучатель
                    ИНАЧЕ Продажи.Документ.Контрагент
                КОНЕЦ) КАК КлиентыСКоличествомДней,
            (ВЫБРАТЬ
                СУММА(Продажи.Документ.СуммаДокумента) КАК ОбщаяВыручка
            ИЗ
                РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
            ГДЕ
                (&Контрагенты = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
                    ИЛИ Продажи.Документ.Контрагент В (&Контрагенты)
                    ИЛИ Продажи.Документ.Контрагент В ИЕРАРХИИ(&Контрагенты))
            ) КАК Итоги
        СГРУППИРОВАТЬ ПО
            КлиентыСКоличествомДней.КоличествоДней,
            Итоги.ОбщаяВыручка) КАК ГруппыПоДням
            
    ОБЪЕДИНИТЬ ВСЕ
            
    ВЫБРАТЬ
        // Уровень 3 - Клиенты
        0,
        Детализация.КлиентНаименование,
        Детализация.ДоляКлиента,
        Детализация.СуммаПоКлиенту
    ИЗ
        (ВЫБРАТЬ
            Клиенты.СуммаПоКлиенту,
            Клиенты.КлиентНаименование,
            Итоги.ОбщаяВыручка,
            ВЫБОР
                КОГДА Итоги.ОбщаяВыручка > 0
                    ТОГДА Клиенты.СуммаПоКлиенту / Итоги.ОбщаяВыручка * 100
                ИНАЧЕ 0
            КОНЕЦ КАК ДоляКлиента
        ИЗ
            (ВЫБРАТЬ
                СУММА(Продажи.Документ.СуммаДокумента) КАК СуммаПоКлиенту,
                ВЫБОР
                    КОГДА Продажи.Документ.РеальныйПолучатель <> НЕОПРЕДЕЛЕНО
                        И Продажи.Документ.РеальныйПолучатель <> Продажи.Документ.Контрагент
                        ТОГДА Продажи.Документ.РеальныйПолучатель.Наименование
                    ИНАЧЕ Продажи.Документ.Контрагент.Наименование
                КОНЕЦ КАК КлиентНаименование
            ИЗ
                РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
            ГДЕ
                (&Контрагенты = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
                    ИЛИ Продажи.Документ.Контрагент В (&Контрагенты)
                    ИЛИ Продажи.Документ.Контрагент В ИЕРАРХИИ(&Контрагенты))
            СГРУППИРОВАТЬ ПО
                ВЫБОР
                    КОГДА Продажи.Документ.РеальныйПолучатель <> НЕОПРЕДЕЛЕНО
                        И Продажи.Документ.РеальныйПолучатель <> Продажи.Документ.Контрагент
                        ТОГДА Продажи.Документ.РеальныйПолучатель.Наименование
                    ИНАЧЕ Продажи.Документ.Контрагент.Наименование
                КОНЕЦ) КАК Клиенты,
            (ВЫБРАТЬ
                СУММА(Продажи.Документ.СуммаДокумента) КАК ОбщаяВыручка
            ИЗ
                РегистрНакопления.Продажи.Обороты(&ПериодС, &ПериодПо, , ) КАК Продажи
            ГДЕ
                (&Контрагенты = ЗНАЧЕНИЕ(Справочник.Контрагенты.ПустаяСсылка)
                    ИЛИ Продажи.Документ.Контрагент В (&Контрагенты)
                    ИЛИ Продажи.Документ.Контрагент В ИЕРАРХИИ(&Контрагенты))
            ) КАК Итоги
        ) КАК Детализация
    

    Обратите внимание, что в данном запросе мы заменили прямые обращения к Документ.РасходнаяНакладная на РегистрНакопления.Продажи.Обороты. Это существенное улучшение.

Причина 3: Ошибки в структуре отчета СКД

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

  1. Отсутствие выбранных полей или группировок.

    В настройках отчета (на вкладке "Настройки" схемы компоновки данных) необходимо явно указать, какие поля вы хотите видеть в отчете и как они должны быть сгруппированы. Если вы не добавили ни "Детальные записи", ни группировки, то СКД не будет знать, что отображать.

    1. Откройте схему компоновки данных.
    2. Перейдите на вкладку "Настройки".
    3. В секции "Структура" добавьте элемент, например, "Таблица".
    4. Для этого элемента добавьте "Выбранные поля", перетащив нужные поля из списка доступных полей.
    5. Если вам нужна детализация, добавьте "Детальные записи" и выберите поля для них.
    6. Если нужны итоги, настройте "Группировки".
  2. Неопределенные ресурсы.

    Если ваш отчет предполагает использование агрегатных функций (суммы, количества, средние значения), убедитесь, что они корректно определены на вкладке "Ресурсы" схемы компоновки данных и выбраны в настройках отчета.

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

    1. Перейдите на вкладку "Ресурсы".
    2. Убедитесь, что для ваших полей-ресурсов (например, Выручка, КоличествоДнейСПродажами) указаны соответствующие выражения (например, Сумма(Выручка)).
    3. Убедитесь, что эти ресурсы выбраны для отображения в настройках отчета (на вкладке "Настройки").

Отладка: Используем "Консоль СКД"

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

  1. Что показывает "Консоль СКД"?

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

    • Убедиться, что СКД не удалила критичные поля.
    • Проверить, как были применены параметры и отборы.
    • Выявить потенциальные ошибки в запросе, которые проявляются только при компоновке данных.
  2. Как использовать?

    Загрузите вашу схему компоновки данных в "Консоль СКД", установите необходимые параметры и выполните отчет. Затем вы сможете проанализировать сгенерированный запрос и увидеть реальные данные, которые СКД получает перед построением отчета.

Мы проанализировали основные причины, по которым отчет СКД может быть пустым, несмотря на корректный запрос в консоли. Систематически проверяйте каждый из этих пунктов: от пометки обязательных полей до настройки параметров и структуры отчета, а также активно используйте "Консоль СКД" для отладки. Такой подход поможет вам быстро находить и устранять проблемы, делая ваши отчеты работоспособными и информативными.

← К списку