При разработке отчетов или механизмов анализа данных в 1С:Предприятие программисты часто сталкиваются с ситуацией, когда синтаксически верный запрос к виртуальной таблице РегистрБухгалтерии.Хозрасчетный.Остатки возвращает пустую таблицу значений, хотя данные в базе гарантированно присутствуют. Особенно часто это проявляется при попытке получить остатки в разрезе нескольких видов субконто (например, "Контрагенты" и "Договоры").
В данной статье мы подробно разберем, почему это происходит, как влияют версии платформы на работу запросов и какие обходные пути существуют для решения этой проблемы.
Рассмотрим классический пример запроса, который на первый взгляд написан абсолютно правильно. Разберем ситуацию, когда нам необходимо получить остатки по конкретным видам субконто:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Организация,
| ХозрасчетныйОстатки.Счет,
| ХозрасчетныйОстатки.СуммаОстатокДт,
| ХозрасчетныйОстатки.СуммаОстатокКт,
| ХозрасчетныйОстатки.Субконто1 КАК Субконто1,
| ХозрасчетныйОстатки.Субконто2 КАК Субконто2
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(, , &СписокСубконто, ) КАК ХозрасчетныйОстатки";
СписокСубконто = Новый Массив;
СписокСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты);
СписокСубконто.Добавить(ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Договоры);
Запрос.УстановитьПараметр("СписокСубконто", СписокСубконто);
Результат = Запрос.Выполнить().Выгрузить();
Проанализируем параметры виртуальной таблицы Остатки. Согласно документации Синтаксис-помощника, параметры располагаются в следующем порядке:
В приведенном коде массив видов субконто передается в третий параметр. Это совершенно корректно с точки зрения платформы 1С. Этот параметр определяет, какие именно значения будут подставлены в поля Субконто1, Субконто2 и так далее, исходя из их порядка в массиве, а также накладывает фильтр на счета, у которых данные виды субконто определены в плане счетов.
Выясним причину, по которой код может перестать работать после обновления. Как показывает практика, в релизах платформы, начиная с 8.3.12.1412, был изменен внутренний механизм оптимизации запросов к виртуальным таблицам бухгалтерии. В некоторых случаях это привело к возникновению ошибки («бага»), когда использование массива в третьем параметре (Субконто) приводит к формированию некорректного SQL-запроса к базе данных.
Рассмотрим симптомы этой проблемы:
Проанализируем ситуацию: если платформа некорректно обрабатывает типизацию колонок при передаче массива, она может добавить в SQL-запрос заведомо ложное условие (например, WHERE 1=0), что и приводит к пустой выборке.
Если вы столкнулись с некорректной работой третьего параметра, разберем самый надежный способ обхода — перенос фильтрации в четвертый параметр виртуальной таблицы. Вместо того чтобы ограничивать виды субконто через типизацию, мы явно укажем условие на значения.
Посмотрим на пример измененного запроса:
Запрос.Текст =
"ВЫБРАТЬ
| ХозрасчетныйОстатки.Организация,
| ХозрасчетныйОстатки.Счет,
| ХозрасчетныйОстатки.Субконто1,
| ХозрасчетныйОстатки.СуммаОстаток
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(, , ,
| Субконто1 ССЫЛКА Справочник.Контрагенты
| ИЛИ Субконто2 ССЫЛКА Справочник.ДоговорыКонтрагентов) КАК ХозрасчетныйОстатки";
Важный нюанс: при таком подходе мы оставляем третий параметр пустым. Это заставляет систему выбирать все доступные субконто, а затем фильтровать их. Это может быть чуть медленнее на огромных базах, но гарантирует получение результата.
Иногда причина кроется не в коде, а в состоянии базы данных. Посмотрим, какие технические действия могут помочь:
Проанализируем еще одну особенность: виртуальная таблица Остатки без указания счета (второй параметр) пытается собрать данные по всем счетам плана счетов. Если в параметре Субконто передан массив, платформа пытается сопоставить этот массив с каждым счетом. Если у счета количество субконто меньше, чем в массиве, или они имеют другие типы, механизм сопоставления может дать сбой.
Попробуем добавить явный фильтр по счету (например, 60 или 62), где эти субконто точно есть:
Запрос.Текст =
"ВЫБРАТЬ ...
|ИЗ
| РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет В ИЕРАРХИИ (&СчетаРасчетов), &СписокСубконто, ) КАК ХозрасчетныйОстатки";
СписокСчетов = Новый Массив;
СписокСчетов.Добавить(ПланыСчетов.Хозрасчетный.РасчетыСПоставщиками);
СписокСчетов.Добавить(ПланыСчетов.Хозрасчетный.РасчетыСПокупателями);
Запрос.УстановитьПараметр("СчетаРасчетов", СписокСчетов);
В большинстве случаев явное указание счета "подсказывает" оптимизатору платформы правильный путь к данным и устраняет проблему пустого результата.
Если ваш запрос к остаткам возвращает пустую таблицу значений:
Субконто не массив, а одно значение ПланыВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты. Если так работает, значит, проблема именно в обработке массивов.Соблюдение этих рекомендаций позволит вам писать отказоустойчивый код, который будет работать корректно вне зависимости от обновлений платформы 1С.