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