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