Перевод базы данных с файлового режима на клиент-серверный (SQL) часто преподносит сюрпризы разработчикам 1С. Одна из самых распространенных ситуаций: отчет, созданный на системе компоновки данных (СКД), который идеально работал на локальной копии, внезапно перестает выводить расчетные показатели (например, проценты) на рабочем сервере. При этом количественные данные выводятся, а формулы возвращают пустые значения или нули. Разберем детально причины этого поведения и способы решения проблемы.
Проанализируем фрагмент запроса, предоставленный автором темы. В тексте запроса расчет процентов выполняется следующим образом:
ВЫБОР
КОГДА ВТ_Все.КоличествоВсего = 0 ТОГДА 0
ИНАЧЕ ВТ_Все.КоличествоПродаж / ВТ_Все.КоличествоВсего * 100
КОНЕЦ КАК ПроцентКП
В файловом варианте (встроенная СУБД 1С) деление двух целых чисел часто автоматически преобразуется в число с плавающей точкой. Однако Microsoft SQL Server работает иначе: если оба операнда (делимое и делитель) имеют целочисленный тип, результат деления также будет целым числом. Если КоличествоПродаж (например, 5) меньше, чем КоличествоВсего (например, 10), то результатом деления 5 / 10 в SQL будет 0, а не 0.5. Умножение на 100 в конце уже не спасает ситуацию, так как данные потеряны на этапе деления.
Как исправить: Необходимо принудительно привести одно из чисел к дробному типу. Самый простой способ — умножить числитель на 1.0. Рассмотрим исправленный вариант:
ВЫБОР
КОГДА ВТ_Все.КоличествоВсего = 0 ТОГДА 0
ИНАЧЕ (ВТ_Все.КоличествоПродаж * 1.0) / ВТ_Все.КоличествоВсего * 100
КОНЕЦ КАК ПроцентКП
Проанализируем ситуацию с использованием соединений. В запросе автора активно используются ЛЕВОЕ СОЕДИНЕНИЕ и функция ЕСТЬNULL. В серверном режиме SQL более строго относится к значениям NULL. Если при расчете сложного выражения хотя бы один элемент окажется NULL (например, из-за отсутствия данных в одной из временных таблиц), то результатом всего выражения может стать NULL.
Выясним причину: в файловой базе 1С иногда «прощает» отсутствие ЕСТЬNULL в сложных цепочках сложения, но на сервере это недопустимо. Проверьте, чтобы каждое поле, участвующее в расчетах (особенно в знаменателе или при суммировании), было обернуто в ЕСТЬNULL(Поле, 0).
В сообщениях форума упоминается, что «помогло разделение процедур на клиенте и на сервере». Разберем, что это значит для СКД. Система компоновки данных всегда выполняется на стороне сервера. Если вы программно заполняете параметры отчета или настройки компоновки в модуле формы, убедитесь, что этот код выполняется в контексте, доступном серверу.
&ВидЦены) устанавливаются в процедуре ПриОткрытии на клиенте, они могут не передаться в схему, если вы используете нестандартный вывод отчета.ПриКомпоновкеРезультата, весь код внутри должен быть серверным.ВЫРАЗИТЬ или программно) может работать по-разному в зависимости от того, установлены ли необходимые привилегии и доступна ли общая папка для временных файлов сервера 1С.Как отмечают участники обсуждения, иногда проблема кроется в «дичи» серверного кэша. SQL Server строит план запроса один раз и сохраняет его. Если структура временных таблиц или типы данных изменились, сервер может выдавать неактуальный результат. Рассмотрим шаги по диагностике:
Агент сервера 1С:Предприятие.В сообщении №16 автор задает важный вопрос: как получить корректную сумму, если цены в разных документах отличаются, но в отчете нужно видеть только общие итоги по номенклатуре (без списка документов)?
Проанализируем ошибку: если мы просто уберем группировку по документам в итоговом запросе и напишем МАКСИМУМ(Цена), СКД возьмет самую большую цену из всех документов за период и умножит её на суммарное количество. Это даст огромную ошибку в деньгах.
Правильный подход:
ВТ_Возвраты) обязательно считайте сумму сразу: Количество * Цена КАК Сумма. Это нужно делать до того, как вы схлопнете данные по номенклатуре.Сумма как СУММА(Сумма).Количество как СУММА(Количество).ВЫБОР КОГДА Сумма(КоличествоВсего) = 0 ТОГДА 0 ИНАЧЕ Сумма(КоличествоПродаж) / Сумма(КоличествоВсего) * 100 КОНЕЦ
Посмотрим на пример: такой подход позволит СКД сначала сложить все количества, затем сложить все суммы, рассчитанные построчно (с учетом разных цен в разных документах), и только потом вычислить процент или среднюю цену. При этом в настройках отчета вы сможете спокойно убрать группировку Документ, и данные останутся верными.
Таким образом, для стабильной работы отчета в серверном режиме необходимо соблюдать три правила: явно приводить числа к дробному виду при делении, использовать ресурсы СКД для расчета итоговых показателей и всегда контролировать контекст исполнения кода параметров.