Почему данные в динамическом списке отличаются от результатов в консоли запросов?

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

Разработка сложных интерфейсов, таких как рабочее место кассира (РМК) или менеджерские панели в 1С:Управление торговлей 11, часто требует использования динамических списков с произвольными запросами. Однако программисты нередко сталкиваются с ситуацией: один и тот же запрос в консоли выдает правильные остатки и цены, а в пользовательском режиме (в динамическом списке) отображаются неверные цифры или пустые значения. Рассмотрим детально, почему это происходит и как исправить подобные ошибки.

Особенности механизма компоновки данных в динамических списках

Прежде всего, важно понимать, что динамический список в 1С — это не просто прямой SQL-запрос к базе данных. Это объект, работающий на базе Системы компоновки данных (СКД). Когда платформа исполняет запрос динамического списка, она трансформирует его: добавляет отборы, сортировки, группировки и, что самое важное, механизмы пагинации (выборка данных порциями).

Проанализируем ситуацию, когда в консоли запросов мы видим верный результат, а в списке — нет. Основная причина заключается в том, что итоговый текст запроса, который платформа отправляет на SQL-сервер, может значительно отличаться от того, что вы написали в конфигураторе.

Решение 1: Проверка итогового запроса через консоль СКД

Поскольку динамический список использует СКД, стандартная консоль запросов не всегда показывает реальную картину. Рассмотрим пошагово, как увидеть «настоящий» запрос:

  1. Воспользуемся специализированной Консолью компоновки данных.
  2. Вставим текст запроса из динамического списка в схему компоновки.
  3. Применим те же настройки (отборы, параметры), которые установлены у пользователя в форме.
  4. Выясним, как платформа модифицирует текст. Часто именно на этом этапе становится понятно, что условия ГДЕ накладываются не на конечный результат, а внедряются внутрь вложенных запросов, искажая выборку по остаткам.

Решение 2: Настройка свойства «Использовать всегда»

Платформа 1С оптимизирует выполнение динамического списка. Если какая-то колонка (например, ВНаличииОстаток) не выведена на форму или скрыта пользователем через «Изменить форму», платформа может полностью удалить это поле и связанные с ним соединения (JOIN) из SQL-запроса для ускорения работы.

Разберем ситуацию: если значение остатка используется в сложном выражении ВЫБОР КОГДА или участвует в расчетах в других колонках, его отсутствие в выборке приведет к некорректным результатам. Чтобы этого избежать, необходимо:

  1. Открыть настройки динамического списка в конфигураторе.
  2. Перейти на вкладку «Настройка списка» или открыть список полей.
  3. Для всех полей, которые участвуют в логике (даже если они не видны пользователю), установить флажок «Использовать всегда».

Это гарантирует, что поле ВНаличииОстаток будет присутствовать в запросе независимо от видимости колонки на экране.

Решение 3: Проблема пакетов запросов и временных таблиц

Динамические списки плохо справляются с тяжелыми пакетами запросов, содержащими множество временных таблиц. Рассмотрим пример кода, который может вызвать проблемы в динамическом списке:


ВЫБРАТЬ Номенклатура.Ссылка КАК Ссылка ПОМЕСТИТЬ Товар
ИЗ Справочник.Номенклатура КАК Номенклатура ГДЕ Номенклатура.ПометкаУдаления = ЛОЖЬ;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ Товар.Ссылка КАК Ссылка, СУММА(ЕСТЬNULL(ВложенныйЗапрос.ВНаличииОстаток, 0)) КАК ВНаличииОстаток
ПОМЕСТИТЬ Остатки ИЗ Товар КАК Товар
ЛЕВОЕ СОЕДИНЕНИЕ (
    ВЫБРАТЬ Остатки.Номенклатура, Остатки.ВНаличииОстаток ИЗ РегистрНакопления.СвободныеОстатки.Остатки(&НаДату) КАК Остатки
) КАК ВложенныйЗапрос ПО Товар.Ссылка = ВложенныйЗапрос.Номенклатура
СГРУППИРОВАТЬ ПО Товар.Ссылка;

////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ Остатки.Ссылка, Остатки.ВНаличииОстаток ИЗ Остатки КАК Остатки;

В динамическом списке такой запрос может работать некорректно по следующим причинам:

Рекомендация: Старайтесь избегать временных таблиц в динамических списках. Если расчет остатков слишком сложен, лучше вынести его во вложенный запрос или использовать ВЫБРАТЬ РАЗРЕШЕННЫЕ напрямую из виртуальных таблиц в основном теле запроса.

Решение 4: Влияние RLS (Ограничение доступа на уровне записей)

Проанализируем еще одну частую причину: консоль запросов обычно запускается под правами администратора, а пользователь работает с ограниченными правами. В 1С:УТ 11 механизмы RLS добавляют свои скрытые условия в каждую виртуальную таблицу остатков или цен.

Если в запросе используется РАЗРЕШЕННЫЕ, данные, на которые у пользователя нет прав (например, по конкретному складу или сегменту номенклатуры), просто исчезнут из выборки. При наличии левых соединений это может привести к тому, что по всей строке в колонке остатка будет 0 или NULL.

Решение 5: Параметры виртуальных таблиц

В динамических списках параметры виртуальных таблиц (такие как &НаДату) должны быть правильно инициализированы. Посмотрим на типичную ошибку: если параметр задан в тексте запроса, но не передан в коллекцию Список.Параметры на форме, система может использовать значение по умолчанию (например, пустую дату). Для регистра остатков пустая дата означает получение итогов на 01.01.0001, что всегда даст нулевой результат.

Убедитесь, что в коде формы присутствует установка параметров:


ПараметрДата = Список.Параметры.Найти("НаДату");
Если ПараметрДата <> Неопределено Тогда
    Список.Параметры.УстановитьЗначениеПараметра("НаДату", ТекущаяДата());
КонецЕсли;

Выясняем причины через типизацию данных

Иногда проблема кроется в неявном приведении типов. Если в разных ветках ОБЪЕДИНИТЬ ВСЕ или при использовании ЕСТЬNULL типы данных различаются (например, Число(10,0) и Число(15,3)), динамический список может округлять значения до целого или некорректно отображать дробную часть. Рекомендуется явно использовать функцию ВЫРАЗИТЬ для числовых полей, как это сделано в примере ниже:


ВЫБОР 
    КОГДА ТоварЦены.Номенклатура.ТипНоменклатуры = &Товар 
    ТОГДА ВЫРАЗИТЬ(Остатки.ВНаличииОстаток КАК ЧИСЛО(15, 0)) 
    ИНАЧЕ ВЫРАЗИТЬ(ОстаткиНабораГотовые.ОстатокНабора КАК ЧИСЛО(15, 0)) 
КОНЕЦ КАК ВНаличииОстаток

Подводя итог, если ваш динамический список «врет», последовательно проверьте: наличие флага «Использовать всегда», влияние RLS, корректность передачи параметров и упростите структуру запроса, избавившись от лишних временных таблиц.

← На главную