При работе с регистрами бухгалтерии в 1С программисты часто сталкиваются с ситуацией, когда фильтры, установленные непосредственно в параметрах виртуальной таблицы, выдают неожиданный результат. Особенно это касается таблицы ДвиженияССубконто, где необходимо сопоставить данные по дебету и кредиту. Рассмотрим ситуацию, когда записи, которые должны быть отсечены условием, всё равно попадают в выборку, и разберем, как правильно организовать такой запрос.
Представим сценарий: нам необходимо получить движения по регистру Хозрасчетный, исключив те записи, где второе субконто дебета совпадает со вторым субконто кредита. На первый взгляд, логично прописать это условие прямо в параметрах виртуальной таблицы для оптимизации запроса. Проанализируем пример кода, который вызывает затруднения:
ВЫБРАТЬ
ХозрасчетныйДвиженияССубконто.СчетДт КАК СчетДт,
ХозрасчетныйДвиженияССубконто.СчетКт КАК СчетКт,
ВЫБОР
КОГДА ХозрасчетныйДвиженияССубконто.СубконтоДт2 = ХозрасчетныйДвиженияССубконто.СубконтоКт2
ТОГДА ЛОЖЬ
ИНАЧЕ ИСТИНА
КОНЕЦ КАК Условие,
ХозрасчетныйДвиженияССубконто.СубконтоДт2 КАК СубконтоДт2,
ХозрасчетныйДвиженияССубконто.СубконтоКт2 КАК СубконтоКт2
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачПериода, &КонПериода,
ВЫБОР
КОГДА СубконтоДт2 = СубконтоКт2 ТТГДА ЛОЖЬ
ИНАЧЕ ИСТИНА
КОНЕЦ, , ) КАК ХозрасчетныйДвиженияССубконто
Несмотря на наличие фильтра ВЫБОР...КОНЕЦ в третьем параметре (Условие), в результат запроса все равно попадают строки, где СубконтоДт2 равно СубконтоКт2. Выясним причину, по которой платформа игнорирует или некорректно интерпретирует это выражение.
Для понимания сути проблемы важно помнить, что ДвиженияССубконто — это не физическая таблица в базе данных SQL, а сложный вложенный запрос, формируемый платформой "на лету". Когда мы передаем выражение в параметр Условие, система пытается внедрить его максимально глубоко в подзапросы к физическим таблицам (основной таблице проводок и таблицам значений субконто).
Разберем по шагам, что происходит при сравнении дебета и кредита внутри параметров:
СубконтоДт2 и СубконтоКт2), возникает конфликт. Система может попытаться применить фильтр к промежуточным выборкам, где одна из сторон еще не полностью определена или не соединена с другой.Субконто имеют составной тип. В документации 1С указано, что при использовании операторов сравнения (особенно неравенства <>) для полей типа Характеристика, система может выдавать неверный результат, если не указан конкретный вид субконто. Это связано с тем, что на уровне SQL сравнение составных типов — это сопоставление нескольких полей (типа и значения).Условие фильтры, которые можно применить к "измерениям" или "сторонам" движения независимо (например, СчетДт = &Счет). Сравнение "через сторону" (дебет против кредита) не является штатным сценарием для оптимизатора условий виртуальной таблицы.Самый надежный и корректный способ решить данную проблему — вынести логику сравнения из параметров виртуальной таблицы в основную секцию ГДЕ запроса. Рассмотрим, как изменится наш код:
ВЫБРАТЬ
ХозрасчетныйДвиженияССубконто.СчетДт КАК СчетДт,
ХозрасчетныйДвиженияССубконто.СчетКт КАК СчетКт,
ХозрасчетныйДвиженияССубконто.СубконтоДт2 КАК СубконтоДт2,
ХозрасчетныйДвиженияССубконто.СубконтоКт2 КАК СубконтоКт2
ИЗ
РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто(&НачПериода, &КонПериода, , , ) КАК ХозрасчетныйДвиженияССубконто
ГДЕ
ХозрасчетныйДвиженияССубконто.СубконтоДт2 <> ХозрасчетныйДвиженияССубконто.СубконтоКт2
Почему этот вариант работает правильно? Секция ГДЕ применяется к уже сформированному результату выборки из виртуальной таблицы. В этот момент строка полностью собрана: у нее заполнены и поля дебета, и поля кредита. Платформа выполняет обычное сравнение двух колонок в итоговом наборе данных, что исключает ошибки трансляции, характерные для параметров виртуальных таблиц.
Если специфика задачи требует использования фильтра именно внутри виртуальной таблицы (например, для очень больших объемов данных, где важна каждая доля секунды при работе SQL), необходимо помочь платформе правильно типизировать поля. Для этого в условие добавляется проверка ВидСубконто.
Проанализируем пример такого уточнения:
// В параметре "Условие" виртуальной таблицы
(СубконтоДт2 <> СубконтоКт2
И ВидСубконтоДт2 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты)
И ВидСубконтоКт2 = ЗНАЧЕНИЕ(ПланВидовХарактеристик.ВидыСубконтоХозрасчетные.Контрагенты))
Такой подход заставляет систему жестко типизировать сравниваемые поля на уровне SQL-запроса, что значительно повышает вероятность корректной отработки фильтра. Однако стоит учитывать, что конструкция с ВЫБОР...КОНЕЦ внутри параметров все равно остается нежелательной — лучше использовать прямые логические выражения.
При работе с субконто в виртуальных таблицах следует помнить о нескольких критических моментах:
NULL (что возможно при определенных соединениях внутри виртуальной таблицы), прямое сравнение может дать непредсказуемый результат. В SQL NULL = NULL не возвращает ИСТИНА, поэтому записи могут "пропадать" или "появляться" вопреки логике 1С.ГДЕ является наиболее стабильным решением. Используйте параметры виртуальной таблицы только для простых фильтров по конкретным измерениям или значениям (например, отбор по конкретному СчетДт или конкретной ссылке СубконтоДт1).Таким образом, мы выяснили, что описанное поведение не является ошибкой платформы в чистом виде, а является следствием работы механизмов оптимизации и трансляции запросов. Использование секции ГДЕ гарантирует получение ожидаемого результата при сохранении читаемости и надежности кода.