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