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