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