В процессе работы с системой 1С:Предприятие 8 мы часто сталкиваемся с необходимостью извлекать и анализировать данные из различных источников. Запросы являются мощным инструментом для решения таких задач. Давайте вместе разберем, как объединить информацию из нескольких документов, подсчитать количество определенных элементов (например, контрагентов) и при этом учесть важный аспект – временной период.
Представим ситуацию: нам нужно узнать, сколько раз каждый контрагент упоминался в документах "Поступление товаров и услуг" и "Реализация товаров и услуг". При этом нас интересует статистика за определенный временной интервал. Мы рассмотрим подробное решение этой задачи, используя возможности языка запросов 1С.
Прежде всего, нам необходимо собрать информацию о контрагентах из разных документов в единый набор данных. Для этого мы используем конструкцию
ОБЪЕДИНИТЬ ВСЕ
Рассмотрим структуру запроса, предложенную на форуме, и поясним каждый ее элемент:
ВЫБРАТЬ
Контрагент,
КОЛИЧЕСТВО(*) КАК КоличествоВхождений
ИЗ
(ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Поступление
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Реализация) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
Контрагент
Давайте разберем этот запрос по шагам:
(ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Поступление
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Реализация) КАК ВложенныйЗапрос
Здесь мы сначала формируем временный набор данных. Мы выбираем поле Контрагент из
Документ.Поступление
Контрагент из
Документ.Реализация
ОБЪЕДИНИТЬ ВСЕ гарантирует, что все записи из обоих источников будут включены, даже если они дублируются. Мы используем псевдоним Контрагент КАК Контрагент для единообразия полей при объединении, хотя в данном случае он не строго обязателен, но является хорошей практикой. Весь этот объединенный набор данных получает псевдоним ВложенныйЗапрос, к которому мы будем обращаться в основном запросе.
ВЫБРАТЬ
Контрагент,
КОЛИЧЕСТВО(*) КАК КоличествоВхождений
ИЗ
...
СГРУППИРОВАТЬ ПО
Контрагент
После того как у нас есть единый набор контрагентов, мы приступаем к агрегации. Мы выбираем сам Контрагент и используем агрегатную функцию КОЛИЧЕСТВО(*), которая подсчитывает количество строк для каждой группы. Результату этой функции мы присваиваем псевдоним КоличествоВхождений. Важно понимать, что если в секции
ВЫБРАТЬ
СГРУППИРОВАТЬ ПО
Контрагент.
Как справедливо заметил один из участников форума, в подобных запросах очень важно учитывать временной период. Без него мы получим данные за весь период существования базы, что не всегда информативно. Давайте дополним наш запрос возможностью фильтрации по дате.
Для этого мы добавим в каждый подзапрос секцию
ГДЕ
&.
ВЫБРАТЬ
Контрагент,
КОЛИЧЕСТВО(*) КАК КоличествоВхождений
ИЗ
(ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Поступление
ГДЕ
Документ.Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Контрагент КАК Контрагент
ИЗ
Документ.Реализация
ГДЕ
Документ.Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода) КАК ВложенныйЗапрос
СГРУППИРОВАТЬ ПО
Контрагент
Теперь, прежде чем выполнить этот запрос, нам потребуется установить значения для параметров &НачалоПериода и &КонецПериода с помощью встроенного языка 1С. Рассмотрим пример, как это делается:
Запрос = Новый Запрос;
Запрос.Текст = "
|ВЫБРАТЬ
| Контрагент,
| КОЛИЧЕСТВО(*) КАК КоличествоВхождений
|ИЗ
| (ВЫБРАТЬ
| Контрагент КАК Контрагент
| ИЗ
| Документ.Поступление
| ГДЕ
| Документ.Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода
| ОБЪЕДИНИТЬ ВСЕ
| ВЫБРАТЬ
| Контрагент КАК Контрагент
| ИЗ
| Документ.Реализация
| ГДЕ
| Документ.Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода) КАК ВложенныйЗапрос
|СГРУППИРОВАТЬ ПО
| Контрагент
|";
Запрос.УстановитьПараметр("НачалоПериода", НачалоДня(ТекущаяДата() - 30 * 24 * 3600)); // Например, последние 30 дней
Запрос.УстановитьПараметр("КонецПериода", КонецДня(ТекущаяДата()));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Контрагент: " + Выборка.Контрагент + ", Количество вхождений: " + Выборка.КоличествоВхождений);
КонецЦикла;
В этом примере мы создаем объект Запрос, присваиваем ему текст нашего запроса и затем устанавливаем значения параметров. Для удобства работы с датами в 1С существуют функции
НачалоДня()
КонецДня()
Теперь, когда мы разобрали основную задачу, давайте углубимся в другие важные аспекты работы с запросами в 1С, которые помогут вам строить более сложные и эффективные конструкции.
Язык запросов 1С, хоть и похож на SQL, имеет свои особенности, ориентированные на бизнес-задачи.
ВЫБРАТЬ
Эта секция определяет, какие поля будут включены в результирующую таблицу. Вы можете выбрать все поля с помощью * или перечислить конкретные поля через запятую. Мы также можем использовать псевдонимы (КАК) для полей, чтобы сделать результат более читаемым, как мы делали с КОЛИЧЕСТВО(*) КАК КоличествоВхождений.
ИЗ
Указывает источники данных. Это могут быть таблицы документов, справочников, регистров, а также виртуальные таблицы регистров или результаты других запросов (как в нашем примере с вложенным запросом).
ОБЪЕДИНИТЬ
ОБЪЕДИНИТЬ ВСЕ
Мы уже использовали
ОБЪЕДИНИТЬ ВСЕ
ОБЪЕДИНИТЬ
ГДЕ
Позволяет фильтровать данные по заданным условиям. Мы можем использовать операторы сравнения (=, <>, >, >=, <, <=), логические операторы (И, ИЛИ, НЕ), а также конструкции МЕЖДУ, В, ПОДОБНО и другие.
УПОРЯДОЧИТЬ ПО
Сортирует результат запроса по одному или нескольким полям. По умолчанию сортировка идет по возрастанию (ВОЗР), но мы можем явно указать УБЫВ для сортировки по убыванию.
ВЫБРАТЬ РАЗЛИЧНЫЕ
Если нам нужно получить только уникальные строки в результате запроса, исключая дубликаты, мы используем эту конструкцию.
ПОМЕСТИТЬ
Это очень мощный инструмент для работы со сложными запросами.
ПОМЕСТИТЬ
ВЫБРАТЬ
Контрагент КАК Контрагент
ПОМЕСТИТЬ ВТ_КонтрагентыПоступления
ИЗ
Документ.Поступление
ГДЕ
Документ.Поступление.Дата МЕЖДУ &НачалоПериода И &КонецПериода;
ВЫБРАТЬ
Контрагент КАК Контрагент
ПОМЕСТИТЬ ВТ_КонтрагентыРеализации
ИЗ
Документ.Реализация
ГДЕ
Документ.Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода;
ВЫБРАТЬ
Контрагент,
КОЛИЧЕСТВО(*) КАК КоличествоВхождений
ИЗ
(ВЫБРАТЬ
Контрагент
ИЗ
ВТ_КонтрагентыПоступления
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Контрагент
ИЗ
ВТ_КонтрагентыРеализации) КАК ОбъединенныеКонтрагенты
СГРУППИРОВАТЬ ПО
Контрагент
СОЕДИНЕНИЕ
Позволяет объединять данные из нескольких таблиц по определенному условию. Существуют различные типы соединений:
ВНУТРЕННЕЕ СОЕДИНЕНИЕ
ЛЕВОЕ СОЕДИНЕНИЕ
NULL.
ПРАВОЕ СОЕДИНЕНИЕ
ПОЛНОЕ СОЕДИНЕНИЕ
NULL там, где нет совпадений.Условие соединения задается после ключевого слова ПО.
В 1С запросах доступны функции для манипуляции датами, которые полезны при построении отчетов по периодам. Например:
НАЧАЛОПЕРИОДА(<Дата>, <Период>)
КОНЕЦПЕРИОДА(<Дата>, <Период>)
ГОД(<Дата>)
МЕСЯЦ(<Дата>)
ДЕНЬ(<Дата>)
Для обеспечения высокой производительности системы 1С важно не только правильно писать запросы, но и делать их оптимальными. Давайте проанализируем несколько важных правил:
ГДЕ
Обращение к реквизитам через несколько точек (например, Документ.Контрагент.Партнер) может приводить к неявным соединениям и значительно замедлять выполнение запроса, особенно если поле имеет составной тип. Вместо этого рекомендуем явно использовать соединения (
СОЕДИНЕНИЕ
ВЫРАЗИТЬ
ИЛИ
В
Эти операторы могут приводить к полному сканированию таблиц и снижать производительность. В некоторых случаях их можно переформулировать с помощью
ОБЪЕДИНИТЬ
ПОМЕСТИТЬ
Как мы уже упоминали, использование временных таблиц вместо сложных вложенных запросов может улучшить читаемость и производительность, так как позволяет разбить сложную логику на более простые, кэшируемые шаги.
Виртуальные таблицы (например, регистров накопления, регистров сведений) созданы для удобства, но при их использовании всегда необходимо указывать условия отбора (особенно по периоду), чтобы избежать выборки излишнего объема данных.
Выполнение запросов внутри циклов встроенного языка является одной из самых частых причин низкой производительности. Старайтесь переформулировать логику таким образом, чтобы все необходимые данные были получены одним запросом или с минимальным количеством запросов.
Передача значений через параметры запроса (&Параметр) позволяет платформе кэшировать план запроса, что ускоряет его повторное выполнение. Это также повышает безопасность и читаемость кода.
Мы рассмотрели, как объединять данные из разных источников, группировать их и подсчитывать необходимые значения, а также как учитывать временные периоды. Помните, что практика и эксперименты – ваши лучшие помощники в освоении языка запросов 1С. Успехов в работе!
← К списку