Как работает вложенный запрос 1с

Обновлено: 04.07.2024

Структура кода запроса в 1С легко изучить. Начнем от простого запроса к более сложным вариантам.

Выбрать

Любой запрос имеет команду ВЫБРАТЬ, после которой могут идти дополнительные параметры выборки, которые позднее рассмотрим отдельно:
ПЕРВЫЕ <ЧИСЛОЗАПИСЕЙ>
РАЗЛИЧНЫЕ
РАЗРЕШЕННЫЕ

Далее идет список полей выборки.

Простейший запрос в 1С может иметь такой вид:

Данный запрос вернет таблицу, состоящую из одной строки и одной колонки, в которой будет числовое значение равное 1.

Усложняем запрос: добавим еще поля, разделив их запятой
ВЫБРАТЬ 1, 2, "3"

Этот запрос также вернет 1 строку, но уже с 3 колонками, две из которых содержат числа, а 3 строковое.

Поэтому в языке запросов существует специальный оператор именования КАК <ИмяПоля>, который идет после поля,

Предыдущий запрос можно представить в таком виде:
ВЫБРАТЬ 1 КАК Один, 2 КАК Два, "3" КАК ЦифраТриСтрокой

Имена полей задаются по правилам именования переменных: не могут начинаться со строки, содержать пробелы, не должны повторятся в одной выборке, а также отсутствовать (они поставятся автоматически).
Возможно опускать слово КАК, но лучше такой вариант не использовать, так как конструктор запросов это исправит:
ВЫБРАТЬ ссылка ссылка ИЗ Справочник.ФизическиеЛица

Такие простые запросы конечно имеют место в реальных условиях, как вспомогательные таблицы, но обычно требуется выборка из какого-то источника.

Для этого существует оператор ИЗ <ТаблицаДанных>, в которой источник данных может быть реальной таблицей из базы данных, а также виртуальными таблицами, которые существуют к некоторым таким таблицами или же к временным таблицам.

Пример простого запроса к реальной таблице справочника:

ВЫБРАТЬ ссылка ИЗ Справочник.Контрагенты

В таких запросах мы можем указать конкретные поля, которые нам нужны или указать *.

ВЫБРАТЬ * ИЗ Справочник.Контрагенты

Такой вариант универсальный, но избыточное количество полей замедляет и усложняет их разбор позднее.

Вложенные таблицы

Также возможно обращение к вложенной таблице:

ВЫБРАТЬ * ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КонтактнаяИнформация

Как видите, здесь мы впервые использовали именование таблицы, которое также упрощает работу при написании запроса, это дает возможность обращения по этому имени к полям:

ВЫБРАТЬ КИ.Ссылка ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КИ //так иногда будет короче

Особенностью запросов к вложенным таблицам является то, что возможно обращение к родительской таблице через поле ссылка через точку.

ВЫБРАТЬ Ссылка.Наименование ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КонтактнаяИнформация

Подобная возможность используется и при обращении к реквизитам ссылочных полей: система сама неявно соединит нужные таблицы, но использование такого обращения следует использовать реже (особенно при указании условий в виртуальных таблицах или условий соединения таблиц).

ВЫБРАТЬ Ссылка, ОсновнойДоговор.Наименование КАК НазваниеДоговора ИЗ Справочник.Контрагенты

В данном случае поле ОсновнойДоговор может быть пустым, тогда обращение к его наименованию не вызовет ошибку, но значение будет NULL, поэтому рекомендуется использовать ЕстьNULL.

Дополнительно

Вернемся к запросу

ВЫБРАТЬ КИ.Ссылка ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КИ

В данном запросе, мы не выбираем поля из самой подтаблицы КонтактнаяИнформация, и в случае если в ней несколько строк, то в выборку попадут несколько строк с одинаковым содержимым.

Чтобы избежать этого можно воспользоваться служебным словом РАЗЛИЧНЫЕ: система устранит все дубли автоматически.

ВЫБРАТЬ РАЗЛИЧНЫЕ КИ.Ссылка ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КИ

Если мы хотим ограничить результат выборки количеством записей (например сотней) используем ПЕРВЫЕ, но использовать ее необходимо с осторожностью (иногда эта команда срабатывает раньше, чем применяются условия запросов), следует тестировать запросы основательно.

ВЫБРАТЬ ПЕРВЫЕ 100 КИ.Ссылка ИЗ Справочник.Контрагенты.КонтактнаяИнформация КАК КИ

ВЫБРАТЬ * ИЗ (ВЫБРАТЬ * ИЗ Справочник.Контрагенты) КАК ВложеннаяТаблица

Использование вложенных запросов имеет смысл в случае, если в нем данные как-либо предварительно обрабатываются, а не как в вышеуказанном примере, где это излишне.

В целом, использование временных таблиц и вложенных запросов замедляет выборку, но парадокс в том, что их использование может дать нужный сигнал оптимизатору запросов и эффект получается положительный.
При больших исходных данных, следует проверять оба варианта использования, на предмет скорости исполнения, для принятия окончательного варианта запроса.

Регистр команд, имен и полей запроса не имеет значение: Выбрать и ВыБРатЬ равносильны.


В качестве источника в запросах можно указать несколько разных таблиц. Если не указать никакие условия для связи таблиц, то будет получено декартово произведение (все возможные комбинации строк) или как еще называют перекрестное соединение.

Например, в базе есть 2 таблицы: ЛеваяТаблица и ПраваяТаблица. Состав таблиц следующий:

Соединения в запросах
Соединения в запросах

В результате выполнения следующего запроса:

Будет получен такой результат:

Соединения в запросах

Каждая запись из левой таблицы была связана с каждой записью из правой таблицы.

Виды соединений в запросе

Соединения нужны для того, чтобы соединить строки разных таблиц по какому-либо условию. Условия указываются после ключевого слова ПО. Может быть несколько условий при одном соединении.

Язык запросов 1С поддерживает следующие виды соединений:

  • Внутреннее соединение
  • Левое внешнее соединение
  • Правое внешнее соединение
  • Полное внешнее соединение

В запросах позволяется не указывать слова внутреннее и внешнее.

Внутреннее соединение

В результате внутреннего соединения таблиц в выборку попадут только те записи, которые удовлетворяют условию соединения:

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.ПраваяТаблица КАК ПраваяТаблица

Внутреннее соединение

В результат запроса не попала четвертая запись из левой таблицы, потому что для нее не нашлось записи в правой таблице, которая бы удовлетворяла условию ЛеваяТаблица.Код = ПраваяТаблица.Код.

Левое соединение

В результате левого соединения таблиц в выборку попадут все записи из левой таблицы, и только те записи из правой таблицы, которые удовлетворяют условию соединения:

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПраваяТаблица КАК ПраваяТаблица

Левое соединение

В четвертой строке в полях ПравоеНаименование и ПравыйКод будет NULL.

Правое соединение

Это то же самое, что и левое соединение, только таблицы меняются местами. В результате правого соединения таблиц в выборку попадут все записи из правой таблицы, и только те записи из левой таблицы, которые удовлетворяют условию соединения. Очень редко используется на практике:

ПРАВОЕ СОЕДИНЕНИЕ Справочник.ПраваяТаблица КАК ПраваяТаблица

Правое соединение

В четвертой строке в полях ЛевоеНаименование и ЛевыйКод будет NULL.

Полное соединение

ПОЛНОЕ СОЕДИНЕНИЕ Справочник.ЛеваяТаблица КАК ЛеваяТаблица

Полное соединение

В четвертой строке в полях ЛевоеНаименование и ЛевыйКод будет NULL. В пятой строке в полях ПравоеНаименование и ПравыйКод будет NULL.

Два левых соединения в запросе

Допустим, что есть еще одна таблица со следующим содержимым:

Два левых соединения

И нужно связать и ее и правую таблицу с левой. Для этого можно использовать два левых соединения:

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПраваяТаблица КАК ПраваяТаблица ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ЕщеТаблица КАК ЕщеТаблица

Два левых соединения

Точно также можно связать и три таблицы, и четыре и т.д. То же самое относится и к внутреннему, правому и полному соединению.

Левое соединение с условием

Если при левом соединении наложить условие на поле правой таблицы, то соединение будет автоматически преобразовано во внутреннее соединение:

ЛЕВОЕ СОЕДИНЕНИЕ Справочник.ПраваяТаблица КАК ПраваяТаблица

Левое соединение с условием

Чтобы получить правильный результат нужно условие перенести из предложения ГДЕ в условие соединения:

Анна Викулина

Протестируйте качество нашей работы - получите первую консультацию в подарок.

Конструкцию «РАЗРЕШЕННЫЕ» можно часто увидеть в запросах в системах 1С, в которых используются ограничения доступа на уровне записей. Это достаточно полезный механизм, позволяющий тонко настроить права для пользователей в зависимости от их значений. К примеру, разные менеджеры по продажам должны видеть документы только своих контрагентов. И если они пользуются одним отчетом, то именно использование оператора «РАЗРЕШЕННЫЕ» в запросе поможет избежать ошибки.

Возникновение ошибки

Если по какой-то причине не использовалась конструкция «РАЗРЕШЕННЫЕ», а в запросе выбираются данные пользователями, у которых настроено RLS, возникнет ошибка. Система 1С сообщит нам о том, что у текущего пользователя не хватает прав, чтобы выполнить запрос. При обычной выборке 1С последовательно берет записи из таблицы базы данных и читает их с правами пользователя. Когда попадается строка с данными скрытыми от пользователя с помощью RLS, запрос останавливается с ошибкой.

При добавлении команды «РАЗРЕШЕННЫЕ» после ключевого слова «ВЫБРАТЬ» ошибка уйдет, и наш запрос успешно выполнится независимо от настроек RLS. Помните, что данный оператор добавляется только в выборку верхнего уровня и влияет на весь запрос целиком и вложенные алгоритмы. Многие программисты так и поступают практически в каждом случае, считая это идеальным решением. Конечно, добавить «РАЗРЕШЕННЫЕ» – простейшее действие, но оно имеет существенный недостаток.

Именно поэтому при написании запроса с использованием оператора «РАЗРЕШЕННЫЕ» необходимо помнить про его особенности. Грамотное его применение способно существенно облегчить работу пользователей и убрать лишнюю информацию из их интерфейса. Но и слишком частое его использование приведет к тому, что отдельным сотрудникам может подаваться недостоверная информация. Это означает, что необходимо найти пути отражения ограниченной информации без использования «РАЗРЕШЕННЫЕ» в запросе 1С.

Как можно обойтись без «РАЗРЕШЕННЫЕ»?

После решения о том, что для важных отчетов лучше обойтись без использования конструкции «РАЗРЕШЕННЫЕ», нужно решить, как избежать ошибок. Исходя из вышенаписанного, нам нужно, чтобы при выполнении запроса система выбирала только те записи, права на которые есть у пользователя. Существует два способа получить нужный результат.

Первый заключается в том, чтобы перенести данные с ограничениями во вложенный запрос. Некоторым СУБД вполне хватает этого, чтобы проверка доступа отработала без ошибок и выдала ограниченные записи. Успех зависит от варианта реализации ограничений доступа на этом уровне.

Второй метод заключается в том, чтобы в запросе задать отбор по настройкам для конкретного пользователя. Реализация этого может быть разной – можно использовать соединение с таблицей настроек прав доступа или же задать ограничение при помощи параметра.

Второй вариант наиболее предпочтителен при формировании отчетов, так как достаточно универсален. Пользователи с различными правами могут пользоваться одним отчетом, если правильно выберут контрагента, подразделение или любой другой отбор, фигурирующий в RLS. Если же этого не будет сделано, то выплывет ошибка, информирующая об отсутствии прав на просмотр данных.

Разграничение прав доступа на уровне записей – достаточно сложная и тонкая настройка, особенно в системах с множеством пользователей. Оператор «РАЗРЕШЕННЫЕ» существенно облегчает учет ограничений в запросах. Но подходить к его использованию нужно, предварительно продумав, не возникнет ли впоследствии недопонимания между пользователями. Иногда лучше обязать сотрудников настраивать лишний фильтр, чем выискивать источники несоответствия в будущем.

Вложенным называется запрос, который является источником выборки основного запроса. Допускается произвольная вложенность таких запросов.

  • Предназначен для предварительной обработке данных, либо для более удобного восприятия.
  • Может использоваться в качестве параметра условия В()

Синтаксис вложенного запроса:

ВЫБРАТЬ * из (ВЫБРАТЬ 1) КАК ВложенныйЗапрос

ВЫБРАТЬ * ИЗ Справочник.Контрагенты ГДЕ Ссылка В (ВЫБРАТЬсколько с Ссылка ИЗ Справочник.Контрагенты)

ВЫБРАТЬ * ИЗ Справочник.Контрагенты ГДЕ (Ссылка,Наименование) В (ВЫБРАТЬ Ссылка,Наименование ИЗ Справочник.Контрагенты)


В конструкторе вложенный запрос создается на основной вкладке по специальной кнопке:


Иконка у таблицы вложенного запроса отличается от других таблиц:

Прочие сведения о вложенных запросах

Считается, что вложенные запросы менее оптимизированы на скорость, но с появлением платформы 8.3 данный фактор справедлив только для Postgres SQL (возможно особенность конкретной сборки).

В целом, в большинстве случаев, запросы можно переписать на использование временных таблиц, но не для запроса динамического списка управляемого интерфейса (там это запрещено на уровне платформы). Вложенный запрос же использовать в нем допустимо, если он не вызывает дублей ключевых полей (Ссылка).

Если вложенный запрос основной, то основная таблица динамического списка будет пустой, что отключит событийные команды такого списка.
(для примера выше, нельзя будет добавить новый элемент или группу).

Допускается вложенный запрос и при соединениях таблиц.

Например:

ВЫБРАТЬ * ИЗ Справочник.Контрагенты КАК Основная ЛЕВОЕ СОЕДИНЕНИЕ (ВЫБРАТЬ * ИЗ Справочник.Контрагенты ) КАК Вложенный ПО Основная.Ссылка = Вложенный.Ссылка

Примеры выше подобраны в учебных целях: максимально простого синтаксиса, а не для решения какой-либо задачи.

Зачем может потребоваться вложенный запрос в приоритетном порядке:

В случае использования результата агрегатной функции в качестве условия соединения таблиц:

  • Для простого отбора можно воспользоваться конструкцией ИМЕЮЩИЕ.
    Если же нам необходимо посчитать остаток в рознице + в опте (в торговле) и вывести только, те у которых общий остаток меньше 10, без вложенного запроса невозможно будет обойтись.
  • Условия в запросах виртуальных таблиц работают лучше и быстрее, если используется В(), вместо обращения через точку:

ВЫБРАТЬ * ИЗ РегистрСведений.КурсыВалют.СрезПоследних(, Валюта В(ВЫБРАТЬ ссылка из Справочник.Валюты. ГДЕ Наименование = "Рубль"))

ВЫБРАТЬ * ИЗ РегистрСведений.КурсыВалют.СрезПоследних(, Валюта.Наименование = "Рубль")

Раньше люди нуждались в продуктах, чтобы выжить. Теперь продукты нуждаются в людях, чтобы выжить.

— Николас Джонсон

Читайте также: