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