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

Программист 1С v8.3 (Обычные формы) 1С:Зарплата и Управление Персоналом IT и автоматизация бизнеса
← На главную

При разработке отчетов в 1С разработчики нередко сталкиваются с ситуацией, когда текст запроса в обычной консоли запросов выполняется корректно и возвращает все строки, однако при переносе в схему компоновки данных (СКД) или консоль отчетов часть колонок (особенно полученных через ЛЕВОЕ СОЕДИНЕНИЕ) оказывается пустой либо строки вовсе пропадают. Разберем по шагам причины такого поведения платформы и рассмотрим лучшие практики построения запросов по начислениям.

Причины расхождения поведения СКД и обычной консоли запросов

Схема компоновки данных — это не просто инструмент исполнения запроса, а интеллектуальный генератор итогового текста SQL-запроса. Проанализируем основные факторы, вызывающие различия:

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

Вариант 1. Замена множественных соединений на конструкцию ВЫБОР КОГДА

Рассмотрим исходный ошибочный подход: разработчик многократно присоединяет одну и ту же табличную часть документа к шапке документа через ЛЕВОЕ СОЕДИНЕНИЕ, накладывая условия по видам расчета в секции ПО. Такой подход создает избыточную нагрузку на СУБД (декартово произведение строк табличных частей) и часто приводит к непредсказуемой оптимизации запроса внутри СКД.

Вместо нескольких соединений объединим выборку по видам расчета в одно левое соединение с условной агрегацией:


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

Вариант 2. Оптимальный выбор данных из табличной части без лишних соединений

Проанализируем структуру данных: если в отчет не требуется выводить пустые документы (без строк начислений), нет необходимости выбирать шапку документа и соединять ее с табличной частью. Гораздо эффективнее строить запрос напрямую к табличной части Документ.НачислениеПоБольничномуЛисту.Начисления, а реквизиты шапки документа получать через обращение к ссылке.

Посмотрим на пример такого запроса:


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

Рекомендации по настройке схемы компоновки данных

Для гарантированного вывода результатов в СКД выполним следующие шаги:

  1. Настройка полей ресурсов: Перейдем на закладку Ресурсы в схеме компоновки. Добавим поля ДниЗаСчетРаботодателя, ДниЗаСчетФСС, ПособиеЗаСчетРаботодателя, ПособиеЗаСчетФСС с формулой Сумма(...).
  2. Отказ от жесткого отбора по кодам: Поиск видов расчета по строковым кодам (например, "00025") делает отчет чувствительным к изменениям в пользовательской базе. Рекомендуется выносить список видов расчета в параметры СКД либо использовать предопределенные элементы планов видов расчета.
  3. Обязательность полей: Если поле из соединения все же должно безусловно участвовать в запросе, на вкладке Наборы данных в свойствах поля можно активировать признак Использовать всегда (Автоколонки). Это запретит оптимизатору СКД исключать связь из итогового запроса к базе данных.
← На главную