Как правильно отобрать движения по субконто в РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто, если на счете нет субконто?

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

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

В этой статье мы подробно проанализируем причину возникновения этой проблемы, разберем особенности работы трехзначной логики SQL при обращении к субконто и рассмотрим эффективные варианты решения задачи.

В чем заключается проблема?

Рассмотрим типовую ситуацию. Вы пытаетесь выбрать все движения за период, где в качестве субконто по дебету или по кредиту выступает элемент из массива &ВыборКонтр. На первый взгляд, кажется логичным написать следующий запрос:


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

Если у счета по дебету отсутствует субконто (например, счет 50 «Касса» без аналитики), то поля СубконтоДт1, СубконтоДт2 и СубконтоДт3 принимают значение NULL. При вычислении условий с оператором В (&Массив) выражение с NULL возвращает неопределенный результат (UNKNOWN). Из-за особенностей генерации SQL-запроса платформой 1С при обработке параметров виртуальной таблицы ДвиженияССубконто вся строка проводки исключается из итоговой выборки, даже если по кредиту нужная аналитика присутствует.

Способ 1. Использование подзапроса к виртуальной таблице «Субконто» (Рекомендуемый)

Наиболее оптимальный по производительности и корректности подход — предварительно отфильтровать документы-регистраторы по таблице РегистрБухгалтерии.Хозрасчетный.Субконто, а затем передать условие на Регистратор в виртуальную таблицу ДвиженияССубконто.

Разберем по шагам, как устроен данный запрос:

  1. Обращаемся к виртуальной таблице Субконто и выбираем регистраторы, у которых поле Значение входит в наш массив значений.
  2. Ограничиваем период в подзапросе для максимального использования индексов.
  3. В параметре «Условие» виртуальной таблицы ДвиженияССубконто накладываем отбор на поле Регистратор.

Посмотрим на пример итогового кода 1С:


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

Преимущества метода: Запрос работает быстро, не теряет проводки с пустой аналитикой на одной из сторон и корректно использует индексы базы данных.

Способ 2. Левое соединение с виртуальной таблицей «Субконто»

Если помимо списка проводок вам необходимо точно знать, какой именно вид субконто совпал с условием, можно объединить таблицу ДвиженияССубконто с базовой таблицей Субконто по регистратору через левое соединение.

Проанализируем этот вариант на примере:


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

Обратите внимание: При левом соединении без предварительного отбора по периоду в параметрах таблицы ДвиженияССубконто объем обрабатываемых данных может существенно вырасти. Поэтому всегда передавайте даты &НачПериода и &КонПериода первым и вторым параметрами виртуальной таблицы.

Способ 3. Перенос условий в секцию ГДЕ с обработкой ЕСТЬNULL

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

Рассмотрим, как выглядит такой подход:


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

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

Подведем итоги

Выяснив причину «исчезновения» проводок без субконто при использовании оператора ИЛИ, мы рекомендуем использовать Способ 1 с фильтрацией по Регистратор через подзапрос к РегистрБухгалтерии.Хозрасчетный.Субконто. Это гарантирует правильность выборки данных и высокий темп работы запроса в СУБД.

← На главную