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