Разработка и Конфигурация · 11 мин
1С: как запросом выбрать все документы
Как в 1С запросом выбрать все документы: ВЫБРАТЬ из таблицы документа, отбор по типам, периодам и проведению, обход всех видов документов, типичные ошибки.
Задача «выбрать все документы запросом» возникает при написании отчётов, обработок переноса данных, сверках и регламентных операциях. В языке запросов 1С это решается конструкцией ВЫБРАТЬ с указанием таблицы документа, а если нужны документы всех видов сразу — потребуется либо перечислить их в объединении, либо обойти метаданные средствами встроенного языка и построить текст запроса динамически.
Важно понимать ограничение: один запрос не может обратиться к «документам вообще» — у него всегда есть конкретная таблица-источник вида Документ.РеализацияТоваровУслуг. Универсального источника «все документы» в языке запросов нет, поэтому для сводной выборки применяют ОБЪЕДИНИТЬ ВСЕ по нескольким таблицам или программную генерацию текста запроса через объект Метаданные.
Ниже разобраны рабочие варианты: выборка документов одного вида, всех видов через объединение, отбор по дате, проведению и организации, а также проверка результата и типичные ошибки, из-за которых запрос возвращает пустоту или падает с ошибкой.
Выборка всех документов одного вида
Простейший случай — получить все документы конкретного вида без фильтров. Запрос обращается к виртуальной таблице документа и возвращает ссылки и основные реквизиты:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка,
Реализация.Дата КАК Дата,
Реализация.Номер КАК Номер,
Реализация.Проведен КАК Проведен
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
УПОРЯДОЧИТЬ ПО
Дата
Такой запрос вернёт все документы вида «Реализация товаров и услуг», включая непроведённые и помеченные на удаление. Это частая причина «лишних» строк в отчётах: пользователь ожидает только проведённые документы, а запрос по умолчанию отдаёт вообще всё содержимое таблицы.
Если нужны только проведённые документы, добавьте условие ГДЕ Проведен = ИСТИНА. Если нужно исключить помеченные на удаление — условие НЕ ПометкаУдаления. Оба условия можно комбинировать через И.
Как выбрать документы всех видов сразу
Когда требуется сводный список всех документов информационной базы — например, для аудита действий пользователей за период — используют объединение выборок из нескольких таблиц. Каждая часть объединения должна возвращать одинаковый набор полей совместимых типов:
ВЫБРАТЬ
Реализация.Ссылка КАК Документ,
Реализация.Дата КАК Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Поступление.Ссылка,
Поступление.Дата
ИЗ
Документ.ПоступлениеТоваровУслуг КАК Поступление
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
СчетФактура.Ссылка,
СчетФактура.Дата
ИЗ
Документ.СчетФактураВыданный КАК СчетФактура
Обратите внимание: поле Ссылка в разных частях объединения имеет разные типы, поэтому итоговая колонка становится составного типа. Это нормально для выборки, но если результат передаётся в СКД или временную таблицу, составные типы могут замедлять соединения и мешать индексированию.
Ограничение подхода очевидно: перечислять вручную десятки видов документов неудобно, а при добавлении нового документа в конфигурацию запрос придётся дорабатывать. Поэтому для универсальных обработок применяют программное построение запроса.
Программный обход всех документов через метаданные
Универсальный способ — сформировать текст запроса в цикле по коллекции Метаданные.Документы. Для каждого вида документа генерируется часть объединения, затем фрагменты склеиваются:
ТекстЗапроса = "";
Для Каждого ДокументМета Из Метаданные.Документы Цикл
Если ТекстЗапроса <> "" Тогда
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|";
КонецЕсли;
ТекстЗапроса = ТекстЗапроса + "ВЫБРАТЬ
| Таб.Ссылка КАК Ссылка,
| Таб.Дата КАК Дата,
| """ + ДокументМета.Имя + """ КАК ВидДокумента
|ИЗ
| Документ." + ДокументМета.Имя + " КАК Таб";
КонецЦикла;
Запрос = Новый Запрос(ТекстЗапроса);
Результат = Запрос.Выполнить().Выгрузить();
Такой код работает на любой конфигурации без доработки. Строковое поле ВидДокумента добавлено специально: по одной ссылке не всегда удобно понять, к какому виду относится документ, а здесь тип виден сразу в результате.
Учтите, что при большом числе видов документов текст запроса получается объёмным, а время выполнения растёт пропорционально сумме размеров всех таблиц. Для разового аудита это приемлемо, но в регламентных заданиях такой запрос стоит ограничивать периодом.
Отбор по периоду, организации и проведению
Практически всегда выборку всех документов ограничивают условиями. Период задают через параметры, а не подстановкой дат в текст запроса — это безопаснее и позволяет платформе переиспользовать план запроса:
ВЫБРАТЬ
Реализация.Ссылка КАК Ссылка,
Реализация.Дата КАК Дата
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
И Реализация.Проведен
И Реализация.Организация = &Организация
Параметры устанавливают перед выполнением: Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ДатаНачала)). Для конца периода используйте КонецДня() либо границу вида Граница(Дата, ВидГраницы.Включая), иначе документы последнего дня, созданные после 00:00:00, в выборку не попадут — это одна из самых распространённых причин «потерянных» документов.
Если запрос строится программно по всем видам документов, условие по дате нужно добавлять в каждую часть объединения. Условие по организации сработает только для тех видов, где такой реквизит есть — перед генерацией проверяйте наличие реквизита через ДокументМета.Реквизиты.Найти("Организация").
- 1Определите, нужны ли все виды документов или конкретный список
- 2Для одного вида напишите ВЫБРАТЬ из таблицы Документ.Имя
- 3Для всех видов сгенерируйте текст запроса циклом по Метаданные.Документы
- 4Добавьте параметры периода и условия Проведен, НЕ ПометкаУдаления
- 5Выполните запрос на тестовой копии и сверьте количество строк с ожиданием
Проверка результата и контрольные точки
После выполнения запроса убедитесь, что выборка соответствует ожиданиям. Самая простая проверка — сравнить количество строк результата с количеством документов, которое показывает список в пользовательском режиме при аналогичном отборе. Расхождение почти всегда означает ошибку в условиях.
Для объединений полезно добавить в выборку КОЛИЧЕСТВО с группировкой по виду документа: так сразу видно, что какой-то вид вернул ноль строк. Ноль может быть нормой (документов этого вида просто нет), но может означать и ошибку в условии конкретной части объединения.
Как проверить результат
Совпадает с отбором в списке документов в пользовательском режиме
Меньше ожидаемого — проверяйте границы периода и условие Проведен
Документы первого и последнего дня присутствуют
Пропали документы последнего дня — конец периода задан без КонецДня()
В сводной выборке есть строки по всем ожидаемым видам
Вид документа отсутствует — он не включён в объединение или условие отсекло все строки
Типичные ошибки и ограничения
Первая ошибка — ожидание, что существует источник «Документы» для всех видов сразу. Такого источника нет: попытка написать ИЗ Документы приведёт к ошибке построения запроса. Только конкретные таблицы или объединение.
Вторая ошибка — забыть про пометку удаления. Помеченные документы физически остаются в таблице до регламентного удаления, и запрос без условия их вернёт. Если обработка дальше что-то пересчитывает по этим данным, итоги будут искажены.
Третья группа проблем связана с правами и RLS. Запрос выполняется с учётом прав текущего пользователя: если у него нет доступа к части документов, они молча не попадут в результат. В привилегированном модуле (УстановитьПривилегированныйРежим) запрос увидит всё — это нужно учитывать, чтобы не выдать пользователю лишние данные.
Альтернативы запросу: выборка и обход в коде
Запрос — не единственный способ получить все документы. Менеджер документа предоставляет метод Выбрать(), который возвращает выборку для последовательного обхода: Документы.РеализацияТоваровУслуг.Выбрать(НачалоПериода, КонецПериода). Это удобно, когда документы нужно по одному обработать в цикле, а не получить таблицей.
Сравнение подходов помогает выбрать инструмент под задачу:
Сравнение вариантов
Подходит для отчётов, СКД, соединений с другими данными. Возвращает всю выборку сразу; требует аккуратности с объёмом
Подходит для последовательной обработки документов в цикле. Не умеет соединения и группировки
Подходит для универсальных обработок по всем видам документов. Текст запроса объёмный, выполняется дольше
Для массовой обработки (например, перепроведения) выборку через Выбрать() часто предпочитают: она не выгружает все ссылки в память разом и позволяет обрабатывать документы порциями с контролем транзакций. Для аналитики и сводных таблиц запрос эффективнее, потому что всю работу выполняет СУБД.
Что важно запомнить
Все документы одного вида выбираются запросом из таблицы Документ.ИмяДокумента; всех видов — через ОБЪЕДИНИТЬ ВСЕ или генерацию текста по Метаданные.Документы. Всегда ограничивайте период, учитывайте пометку удаления, проведение и права доступа, а результат проверяйте сверкой количества строк.
FAQ
Можно ли одним запросом выбрать документы всех видов без ОБЪЕДИНИТЬ?
Нет, в языке запросов 1С нет универсального источника «все документы». Либо перечисляйте таблицы через ОБЪЕДИНИТЬ ВСЕ, либо формируйте текст запроса программно в цикле по Метаданные.Документы — это стандартный приём для универсальных обработок.
Почему запрос возвращает помеченные на удаление документы?
Пометка удаления не удаляет запись из таблицы — документ физически остаётся в базе до регламентной обработки «Удаление помеченных объектов». Добавьте условие НЕ ПометкаУдаления, если такие документы не нужны.
Как выбрать только проведённые документы?
Добавьте в секцию ГДЕ условие Проведен = ИСТИНА или просто Проведен (булево поле можно использовать как условие напрямую). Учтите, что у некоторых видов документов проведение может быть отключено в конфигурации — тогда все они будут непроведёнными.
Почему в выборку не попадают документы последнего дня периода?
Причина почти всегда в границе периода: дата без времени означает 00:00:00, и документы, созданные позже в этот день, отсекаются. Передавайте в параметр КонецДня(ДатаОкончания) или используйте объект Граница с видом «Включая».
У двух пользователей один и тот же запрос даёт разное число строк — это ошибка?
Скорее всего, нет: запрос выполняется с учётом прав доступа и ограничений RLS. Пользователь без доступа к части документов получит меньше строк без каких-либо сообщений. Проверьте права на объекты и записи ролей.
Что быстрее для обхода всех документов — запрос или метод Выбрать()?
Зависит от задачи. Для получения готовой таблицы, группировок и соединений быстрее запрос, так как работу выполняет СУБД. Для поштучной обработки с записью каждого документа удобнее Выбрать(): он не загружает всё в память и позволяет управлять транзакциями по каждому объекту.