При работе с регистрами бухгалтерии в 1С:Предприятие 8 программисты часто сталкиваются с ситуацией, когда фильтр, установленный в параметрах виртуальной таблицы (например, ДвиженияССубконто), работает некорректно. Типичный сценарий: вы устанавливаете отбор по конкретному значению справочника Номенклатура в параметре СубконтоДт1, но в результат запроса «пролезают» записи, где в первом субконто указан Контрагент или другая аналитика. На первый взгляд это кажется багом платформы, но на самом деле это особенность архитектуры системы. Давайте подробно разберем, почему так происходит и как правильно строить такие запросы.
Проанализируем, как платформа 1С воспринимает параметры Субконто1, Субконто2 и Субконто3. В плане счетов для каждого счета задается список видов субконто. Порядок, в котором они указаны (первая строка, вторая, третья), определяет их индекс. Когда мы пишем в запросе СубконтоДт1, мы обращаемся не к конкретному типу данных (например, только к номенклатуре), а к первому по порядку субконто того счета, который попал в выборку.
Рассмотрим ситуацию: в параметре Счет передан список, состоящий из двух счетов: 41 (Товары) и 60 (Расчеты с поставщиками).
Номенклатура.Контрагенты.
Если мы устанавливаем условие СубконтоДт1 = &МойСтанок, платформа пытается применить этот фильтр ко всем записям. Но для счета 60 в колонке Субконто1 физически лежит ссылка на контрагента. Из-за особенностей внутреннего механизма индексации и формирования SQL-запроса платформой, при отсутствии жесткой типизации вида субконто, система может выдать нерелевантные данные или проигнорировать фильтр, если типы данных «перепутались» в контексте разных счетов.
Самый правильный и эффективный способ решить проблему — это «якорение» фильтра с помощью параметра ВидСубконто. Когда мы указываем вид субконто, платформа переключается с позиционного поиска (по номеру колонки 1, 2 или 3) на типизированный поиск по паре «Вид + Значение».
Разберем, как должен выглядеть корректный запрос. Вместо того чтобы просто передать значение, мы явно указываем системе, что нас интересует именно Номенклатура, независимо от того, какой она идет по счету в плане счетов.
ВЫБРАТЬ
ХозрасчетныйДвиженияССубконто.Сумма КАК Сумма,
ХозрасчетныйДвиженияССубконто.СубконтоДт1 КАК Номенклатура
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(
&НачалоПериода,
&КонецПериода,
Счет В (&СписокСчетов)
И ВидСубконтоДт1 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Номенклатура)
И СубконтоДт1 = &НужнаяНоменклатура,
,
) КАК ХозрасчетныйДвиженияССубконто
В данном случае условие ВидСубконтоДт1 гарантирует, что платформа будет искать значение &НужнаяНоменклатура только в тех записях, где первое субконто действительно является номенклатурой. Это исключает попадание контрагентов или других типов в результат.
Если по каким-то причинам вы не можете или не хотите указывать виды субконто (например, аналитика может динамически меняться), можно использовать классическое условие ГДЕ. Выясним причину, почему это работает: условие в параметрах виртуальной таблицы накладывается в процессе формирования этой таблицы на уровне СУБД (используя индексы), а условие ГДЕ накладывается на уже полученный результат выборки.
Посмотрим на пример:
ВЫБРАТЬ
ХозрасчетныйДвиженияССубконто.Сумма,
ХозрасчетныйДвиженияССубконто.СубконтоДт1
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто( , , Счет В (&Счет), , ) КАК ХозрасчетныйДвиженияССубконто
ГДЕ
ХозрасчетныйДвиженияССубконто.СубконтоДт1 = &ПараметрНоменклатура
Важный нюанс: Этот метод всегда работает корректно с точки зрения данных, но он менее производителен. СУБД сначала выберет из базы все движения по счету (включая лишние), и только потом 1С отфильтрует их. На больших объемах данных это может привести к значительным задержкам.
Чтобы лучше понять суть проблемы, проанализируем ситуацию на уровне базы данных. В физических таблицах SQL субконто хранятся в полях типа binary или через механизм смещения типов. Когда выполняется запрос к виртуальной таблице ДвиженияССубконто, платформа делает сложный JOIN с таблицей значений субконто.
Если в плане счетов порядок субконто у счетов разный, то для SQL-запроса поле Субконто1 — это просто контейнер. Без указания ВидСубконто оптимизатор запросов может выбрать неоптимальный план или некорректно сопоставить типы ссылок. Это и приводит к «чудесам», когда в фильтр по ссылке одного справочника попадает ссылка другого. Платформа 1С старается максимально оптимизировать запрос, и иногда эта оптимизация без дополнительных подсказок (видов субконто) дает сбой.
На основе вышеизложенного, выделим правила создания надежных запросов к бухгалтерским регистрам:
ВидСубконтоДтN / ВидСубконтоКтN).Счет передается массив или список значений, убедитесь, что у всех этих счетов нужная вам аналитика находится на одной и той же позиции. Если позиции разные — использование ВидСубконто становится критически обязательным.Субконто3 часто является регистратором), помните, что на разных счетах состав типов в Субконто3 может отличаться. Явное указание вида субконто (например, «Документы расчетов») поможет избежать ошибок типизации.ГДЕ, чтобы гарантировать точность данных.Подведем итог: ошибка «несоблюдения условия» — это не баг, а следствие гибкости настройки планов счетов в 1С. Система позволяет назначать субконто в любом порядке, и программист обязан учитывать этот порядок при написании запросов. Используя связку ВидСубконто + ЗначениеСубконто, вы делаете свой код стабильным и быстрым.