Почему условие в параметрах виртуальной таблицы ДвиженияССубконто работает некорректно при сравнении субконто дебета и кредита?

Программист 1C:Бухгалтерия Бухгалтерский учет
← На главную

При работе с регистрами бухгалтерии в 1С программисты часто сталкиваются с ситуацией, когда фильтры, установленные непосредственно в параметрах виртуальной таблицы, выдают неожиданный результат. Особенно это касается таблицы ДвиженияССубконто, где необходимо сопоставить данные по дебету и кредиту. Рассмотрим ситуацию, когда записи, которые должны быть отсечены условием, всё равно попадают в выборку, и разберем, как правильно организовать такой запрос.

Анализ исходной проблемы

Представим сценарий: нам необходимо получить движения по регистру Хозрасчетный, исключив те записи, где второе субконто дебета совпадает со вторым субконто кредита. На первый взгляд, логично прописать это условие прямо в параметрах виртуальной таблицы для оптимизации запроса. Проанализируем пример кода, который вызывает затруднения:


ВЫБРАТЬ
    ХозрасчетныйДвиженияССубконто.СчетДт КАК СчетДт,
    ХозрасчетныйДвиженияССубконто.СчетКт КАК СчетКт,
    ВЫБОР
        КОГДА ХозрасчетныйДвиженияССубконто.СубконтоДт2 = ХозрасчетныйДвиженияССубконто.СубконтоКт2
            ТОГДА ЛОЖЬ
        ИНАЧЕ ИСТИНА
    КОНЕЦ КАК Условие,
    ХозрасчетныйДвиженияССубконто.СубконтоДт2 КАК СубконтоДт2,
    ХозрасчетныйДвиженияССубконто.СубконтоКт2 КАК СубконтоКт2
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачПериода, &КонПериода, 
        ВЫБОР 
            КОГДА СубконтоДт2 = СубконтоКт2 ТТГДА ЛОЖЬ 
            ИНАЧЕ ИСТИНА 
        КОНЕЦ, , ) КАК ХозрасчетныйДвиженияССубконто

Несмотря на наличие фильтра ВЫБОР...КОНЕЦ в третьем параметре (Условие), в результат запроса все равно попадают строки, где СубконтоДт2 равно СубконтоКт2. Выясним причину, по которой платформа игнорирует или некорректно интерпретирует это выражение.

Особенности трансляции запросов к виртуальным таблицам

Для понимания сути проблемы важно помнить, что ДвиженияССубконто — это не физическая таблица в базе данных SQL, а сложный вложенный запрос, формируемый платформой "на лету". Когда мы передаем выражение в параметр Условие, система пытается внедрить его максимально глубоко в подзапросы к физическим таблицам (основной таблице проводок и таблицам значений субконто).

Разберем по шагам, что происходит при сравнении дебета и кредита внутри параметров:

  1. Разделение сторон движения: На уровне хранения данных в СУБД информация о дебете и кредите может обрабатываться оптимизатором 1С дискретно. Если условие в параметре ссылается одновременно на поля дебета и кредита (СубконтоДт2 и СубконтоКт2), возникает конфликт. Система может попытаться применить фильтр к промежуточным выборкам, где одна из сторон еще не полностью определена или не соединена с другой.
  2. Работа с составными типами данных: Поля Субконто имеют составной тип. В документации 1С указано, что при использовании операторов сравнения (особенно неравенства <>) для полей типа Характеристика, система может выдавать неверный результат, если не указан конкретный вид субконто. Это связано с тем, что на уровне SQL сравнение составных типов — это сопоставление нескольких полей (типа и значения).
  3. Ограничения параметров виртуальной таблицы: Платформа ожидает в параметре Условие фильтры, которые можно применить к "измерениям" или "сторонам" движения независимо (например, СчетДт = &Счет). Сравнение "через сторону" (дебет против кредита) не является штатным сценарием для оптимизатора условий виртуальной таблицы.

Решение 1: Перенос условия в секцию ГДЕ

Самый надежный и корректный способ решить данную проблему — вынести логику сравнения из параметров виртуальной таблицы в основную секцию ГДЕ запроса. Рассмотрим, как изменится наш код:


ВЫБРАТЬ
    ХозрасчетныйДвиженияССубконто.СчетДт КАК СчетДт,
    ХозрасчетныйДвиженияССубконто.СчетКт КАК СчетКт,
    ХозрасчетныйДвиженияССубконто.СубконтоДт2 КАК СубконтоДт2,
    ХозрасчетныйДвиженияССубконто.СубконтоКт2 КАК СубконтоКт2
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачПериода, &КонПериода, , , ) КАК ХозрасчетныйДвиженияССубконто
ГДЕ
    ХозрасчетныйДвиженияССубконто.СубконтоДт2 <> ХозрасчетныйДвиженияССубконто.СубконтоКт2

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

Решение 2: Типизация полей через ВидСубконто

Если специфика задачи требует использования фильтра именно внутри виртуальной таблицы (например, для очень больших объемов данных, где важна каждая доля секунды при работе SQL), необходимо помочь платформе правильно типизировать поля. Для этого в условие добавляется проверка ВидСубконто.

Проанализируем пример такого уточнения:


// В параметре "Условие" виртуальной таблицы
(СубконтоДт2 <> СубконтоКт2 
 И ВидСубконтоДт2 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты)
 И ВидСубконтоКт2 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты))

Такой подход заставляет систему жестко типизировать сравниваемые поля на уровне SQL-запроса, что значительно повышает вероятность корректной отработки фильтра. Однако стоит учитывать, что конструкция с ВЫБОР...КОНЕЦ внутри параметров все равно остается нежелательной — лучше использовать прямые логические выражения.

Важные нюансы и выводы

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

Таким образом, мы выяснили, что описанное поведение не является ошибкой платформы в чистом виде, а является следствием работы механизмов оптимизации и трансляции запросов. Использование секции ГДЕ гарантирует получение ожидаемого результата при сохранении читаемости и надежности кода.

← На главную