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