При разработке отчетов в 1С разработчики нередко сталкиваются с ситуацией, когда текст запроса в обычной консоли запросов выполняется корректно и возвращает все строки, однако при переносе в схему компоновки данных (СКД) или консоль отчетов часть колонок (особенно полученных через ЛЕВОЕ СОЕДИНЕНИЕ) оказывается пустой либо строки вовсе пропадают. Разберем по шагам причины такого поведения платформы и рассмотрим лучшие практики построения запросов по начислениям.
Схема компоновки данных — это не просто инструмент исполнения запроса, а интеллектуальный генератор итогового текста SQL-запроса. Проанализируем основные факторы, вызывающие различия:
ЛЕВОЕ СОЕДИНЕНИЕ из финального запроса. Если в запросе присутствовала группировка верхнего уровня без явного указания полей в ресурсах, оптимизатор может отсечь второе соединение.NULL. В СКД поля, содержащие NULL, без должной обработки функцией ЕСТЬNULL() или без явного указания ресурсов на соответствующей вкладке схемы, могут некорректно схлопываться при группировке строк.СГРУППИРОВАТЬ ПО, а в СКД числовые поля не добавлены на вкладку Ресурсы, компоновщик данных обрабатывает их как измерения группировки. При наличии NULL это приводит к искажению структуры вывода.Рассмотрим исходный ошибочный подход: разработчик многократно присоединяет одну и ту же табличную часть документа к шапке документа через ЛЕВОЕ СОЕДИНЕНИЕ, накладывая условия по видам расчета в секции ПО. Такой подход создает избыточную нагрузку на СУБД (декартово произведение строк табличных частей) и часто приводит к непредсказуемой оптимизации запроса внутри СКД.
Вместо нескольких соединений объединим выборку по видам расчета в одно левое соединение с условной агрегацией:
ВЫБРАТЬ
НачислениеПоБольничномуЛисту.Физлицо КАК ФИО,
НачислениеПоБольничномуЛисту.ДатаНачала,
НачислениеПоБольничномуЛисту.ДатаОкончания,
НачислениеПоБольничномуЛисту.ПериодРегистрации КАК МесяцНачисления,
НачислениеПоБольничномуЛисту.СерияВходящегоДокумента КАК СерияЛисткаНетрудоспособности,
НачислениеПоБольничномуЛисту.НомерВходящегоДокумента КАК NЛисткаНетрудоспособности,
НачислениеПоБольничномуЛисту.КодПричиныНетрудоспособности КАК ПричинаНетрудоспособности,
НачислениеПоБольничномуЛисту.ПроцентОплаты,
ЕСТЬNULL(СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код В ("00021", "00022")
ТОГДА Начисления.ОплаченоДнейЧасов
ИНАЧЕ 0
КОНЕЦ), 0) КАК ДниЗаСчетФСС,
ЕСТЬNULL(СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код = "00025"
ТОГДА Начисления.ОплаченоДнейЧасов
ИНАЧЕ 0
КОНЕЦ), 0) КАК ДниЗаСчетРаботодателя,
ЕСТЬNULL(СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код В ("00021", "00022")
ТОГДА Начисления.Результат
ИНАЧЕ 0
КОНЕЦ), 0) КАК ПособиеЗаСчетФСС,
ЕСТЬNULL(СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код = "00025"
ТОГДА Начисления.Результат
ИНАЧЕ 0
КОНЕЦ), 0) КАК ПособиеЗаСчетРаботодателя
ИЗ
Документ.НачислениеПоБольничномуЛисту КАК НачислениеПоБольничномуЛисту
ЛЕВОЕ СОЕДИНЕНИЕ Документ.НачислениеПоБольничномуЛисту.Начисления КАК Начисления
ПО НачислениеПоБольничномуЛисту.Ссылка = Начисления.Ссылка
И (НЕ Начисления.Сторно)
И (Начисления.ВидРасчета.Код В ("00021", "00022", "00025"))
ГДЕ
НачислениеПоБольничномуЛисту.ПометкаУдаления = ЛОЖЬ
И НачислениеПоБольничномуЛисту.Проведен = ИСТИНА
И НачислениеПоБольничномуЛисту.ПериодРегистрации МЕЖДУ &Дата1 И &Дата2
И НачислениеПоБольничномуЛисту.Организация В(&Организация)
СГРУППИРОВАТЬ ПО
НачислениеПоБольничномуЛисту.Физлицо,
НачислениеПоБольничномуЛисту.ДатаНачала,
НачислениеПоБольничномуЛисту.ДатаОкончания,
НачислениеПоБольничномуЛисту.ПериодРегистрации,
НачислениеПоБольничномуЛисту.СерияВходящегоДокумента,
НачислениеПоБольничномуЛисту.НомерВходящегоДокумента,
НачислениеПоБольничномуЛисту.КодПричиныНетрудоспособности,
НачислениеПоБольничномуЛисту.ПроцентОплаты
Проанализируем структуру данных: если в отчет не требуется выводить пустые документы (без строк начислений), нет необходимости выбирать шапку документа и соединять ее с табличной частью. Гораздо эффективнее строить запрос напрямую к табличной части Документ.НачислениеПоБольничномуЛисту.Начисления, а реквизиты шапки документа получать через обращение к ссылке.
Посмотрим на пример такого запроса:
ВЫБРАТЬ
Начисления.Ссылка.Физлицо КАК ФИО,
Начисления.Ссылка.ДатаНачала КАК ДатаНачала,
Начисления.Ссылка.ДатаОкончания КАК ДатаОкончания,
Начисления.Ссылка.ПериодРегистрации КАК МесяцНачисления,
Начисления.Ссылка.СерияВходящегоДокумента КАК СерияЛисткаНетрудоспособности,
Начисления.Ссылка.НомерВходящегоДокумента КАК NЛисткаНетрудоспособности,
Начисления.Ссылка.КодПричиныНетрудоспособности КАК ПричинаНетрудоспособности,
Начисления.Ссылка.ПроцентОплаты КАК ПроцентОплаты,
СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код = "00025"
ТОГДА Начисления.ОплаченоДнейЧасов
ИНАЧЕ 0
КОНЕЦ) КАК ДниЗаСчетРаботодателя,
СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код = "00025"
ТОГДА Начисления.Результат
ИНАЧЕ 0
КОНЕЦ) КАК ПособиеЗаСчетРаботодателя,
СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код В ("00021", "00022", "00023")
ТОГДА Начисления.ОплаченоДнейЧасов
ИНАЧЕ 0
КОНЕЦ) КАК ДниЗаСчетФСС,
СУММА(ВЫБОР
КОГДА Начисления.ВидРасчета.Код В ("00021", "00022", "00023")
ТОГДА Начисления.Результат
ИНАЧЕ 0
КОНЕЦ) КАК ПособиеЗаСчетФСС
ИЗ
Документ.НачислениеПоБольничномуЛисту.Начисления КАК Начисления
ГДЕ
Начисления.Ссылка.Проведен = ИСТИНА
И Начисления.Ссылка.ПометкаУдаления = ЛОЖЬ
И Начисления.Ссылка.ПериодРегистрации МЕЖДУ &Дата1 И &Дата2
И Начисления.Ссылка.Организация В(&Организация)
И Начисления.ВидРасчета.Код В ("00021", "00022", "00023", "00025")
И НЕ Начисления.Сторно
СГРУППИРОВАТЬ ПО
Начисления.Ссылка.Физлицо,
Начисления.Ссылка.ДатаНачала,
Начисления.Ссылка.ДатаОкончания,
Начисления.Ссылка.ПериодРегистрации,
Начисления.Ссылка.СерияВходящегоДокумента,
Начисления.Ссылка.НомерВходящегоДокумента,
Начисления.Ссылка.КодПричиныНетрудоспособности,
Начисления.Ссылка.ПроцентОплаты
Для гарантированного вывода результатов в СКД выполним следующие шаги:
ДниЗаСчетРаботодателя, ДниЗаСчетФСС, ПособиеЗаСчетРаботодателя, ПособиеЗаСчетФСС с формулой Сумма(...)."00025") делает отчет чувствительным к изменениям в пользовательской базе. Рекомендуется выносить список видов расчета в параметры СКД либо использовать предопределенные элементы планов видов расчета.