Использование вложенных запросов и CTE для работы с объектами доменов

В данном разделе описан синтаксис вложенных запросов и общих табличных выражений (CTE) при настройке правил данных и политик доступа.

В данном разделе при описании RQL-выражений приняты следующие соглашения:

  • Необязательные компоненты выражений заключаются в квадратные скобки.

  • Под обозначением <expression> понимается выражение, то есть применение оператора, функция, идентификатор, литерал, арифметическое выражение или выражение в скобках.

  • Имена функций и операторов RQL могут использоваться как в верхнем, так и в нижнем регистре. В этом разделе имена функций приведены в верхнем регистре, если они являются обертками или имеют прямой аналог среди нативных функций SQL.

Использование промежуточных вычислений (SELECT())

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

Функция select() поддерживает следующие конструкции, переданные как аргументы:

  • указание источника в функции from();

  • объединение с помощью функций join();

  • фильтрация с помощью where();

  • группировка результатов с помощью group();

  • фильтрация результатов группировки с помощью having();

  • сортировка с помощью order();

  • ограничение результата с помощью limit().

Синтаксис
SELECT(<expression>)

Пример

Проверка принадлежности к массиву
constraint: !rql iocType IS NULL OR iocType IN SELECT(UNNEST(ARRAY(@enumIocTypes.Account, @enumIocTypes.Email)))

В данном примере функция SELECT() возвращает результат функции UNNEST() в виде, совместимом с оператором IN. Атрибут iocType объекта, на который действует эффект этого правила, может быть пустым или иметь одно из значений перечисления enumIocTypes — с идентификаторами Account и Email.

Использование общих табличных выражений (функция with())

Функция with() используется для объявления общего табличного выражения (CTE, Common Table Expression). Результат такого выражения сохраняется под псевдонимом и может быть использован в основном запросе или конструкции join().

Синтаксис
with(<alias>, SELECT(<subquery>))

Здесь:

  • <alias> — псевдоним выражения;

  • <subquery> — вложенное выражение, заданное с помощью функции SELECT().

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

  • с помощью функции from: from(@subquery, @sub);

  • напрямую, используя псевдоним.

Конструкцию с with() можно использовать в запросе несколько раз для разных CTE.

Пример
SELECT @sub.side2,
with(
  @sub_query,
  select(
    @links.side2,
    FROM('current', @linkages_allattributes, @links),
     join(
       @doc,
       on(eq(@links.type, @doc.id))
     ),
     where(gt(@links.weight, 100)),
     order(desc(@links.side1)),
     limit(1)
  )
),
FROM(@sub_query, @sub)

В данном запросе:

  1. Формируется вложенный запрос, которому присваивается псевдоним sub_query.

  2. Во вложенном запросе в качестве источника используется связь linkages_allattributes в текущем домене под псевдонимом links.

  3. Выполняется соединение экземпляров связи с текущим объектом. Соединение определяется равенством стороны 1 связи и идентификатора текущего объекта.

  4. Применяется фильтрация: в выборку попадают только те экземпляры связи, у которых значение атрибута weight больше 100.

  5. Результат сортируется по стороне 1 связи в порядке убывания.

  6. Выборка ограничивается одной записью.

  7. Из выборки возвращается значение стороны связи 2.

  8. В основном запросе используется результат вложенного запроса sub_query под псевдонимом sub, из которого выбирается значение стороны связи 2.

Таким образом, из всех экземпляров связи linkages_allattributes, в которых текущий объект находится на стороне 1, выбирается экземпляр с максимальным значением стороны 1, и возвращается значение стороны 2 этого экземпляра.

Использование условий (функция where())

Функция where() аналогична оператору WHERE в основном запросе и позволяет применять к указанным полям выборку по определенному условию.

Условия в where() должны быть переданы в виде функций.
Синтаксис
select(
  <expression>,
  where(<expression>)
)
Пример
where(eq(@links.side1, @doc.id))

Здесь задается условие равенства стороны 1 связи под псевдонимом link и идентификатора текущего объекта.

Группировка (функция group())

Объединять результаты запроса по одному или нескольким полям можно с помощью функции group().

Синтаксис
select(
  <expression>,
  group(
    <field_name_1>,
    <field_name_2>,
    ...,
    <field_name_N>
  )
)

Здесь:

  • <field_name_1> …​ <field_name_N> — имена полей, по которым нужно сгруппировать результаты.

Пример
group(@doc.id, @doc.name)

Здесь результаты запроса группируются по идентификатору и имени текущего объекта.

Фильтрация результатов группировки (функция having())

Если требуется отфильтровать группы данных, полученные после объединения результатов, используйте функцию having(). Использование аналогично функции where(), но в качестве аргументов можно использовать агрегирующие функции.

Синтаксис
select(
  <expression>,
  group(<field_name>),
  having(<expression>)
)
Пример
having(eq(count(@doc.id), 42))

Сортировка возвращаемых результатов (функция order())

Функция order() аналогична оператору ORDER BY в основном запросе и позволяет сортировать результаты запроса по любому полю. Чтобы отсортировать выборку по нескольким полям, передайте в функцию нужные аргументы.

Направление сортировки задается функциями, переданными как аргументы:

  • asc() — по возрастанию;

  • desc() — по убыванию.

Синтаксис
select(
  <expression>,
  order(
    <asc|desc>(field_name_1),
    <asc|desc>(field_name_2),
    ...,
    <asc|desc>(field_name_N)
  )
)

Здесь:

  • <asc|desc> — функции направления сортировки

  • <field_name_1>…​ <field_name_N> — имена полей, по которым нужно отсортировать результаты.

Пример сортировки
order(desc(@links.side1))

Максимальное количество возвращаемых записей (функция limit())

Функция limit() аналогична оператору LIMIT в основном запросе и позволяет ограничить количество возвращаемых записей.

Синтаксис
limit(<m>)

Здесь:

  • <m> — число записей, до которого нужно сократить выборку.

Пример
limit(1)

Примеры использование вложенных запросов

condition: !rql |
  @doc.id = select(@links.side1, from('current', @linkages_allattributes, @links), where(eq(@links.side1, @doc.id)))

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

  • Условие проверяет, что идентификатор текущего объекта совпадает с результатом выборки из связи:

  • Выборка производится из связи linkages_allattributes в текущем домене с псевдонимом links.

  • Условие во вложенном запросе ограничивает поиск только теми экземплярами связи, где на стороне 1 находится текущий объект.

Таким образом, правило применяется, если текущий объект имеет связь linkages_allattributes и находится на стороне 1.

Фильтрация по количеству связей с использованием агрегатной функции

condition: !rql |
  @doc.attributesString IS NULL AND select(count(id), from('current', @linkages_allattributes, @links), where(eq(@links.side1, @doc.id))) > 0

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

  • Производится выборка из связи linkages_allattributes в текущем домене с псевдонимом links:

  • Экземпляры фильтруются по соответствию стороны 1 идентификатору текущего объекта.

  • Внутри вложенного запроса используется агрегатная функция count() для подсчета количества экземпляров в связи linkages_allattributes.

  • Количество экземпляров сравнивается с нулем.

  • Результат вложенного запроса объединяется операцией "И" со вторым условием: @doc.attributesString IS NULL.

Таким образом, правило применяется, если одновременно выполняются два условия: атрибут attributesString текущего объекта не заполнен и количество найденных экземпляров связи больше нуля.

Использование вложенного запроса с сортировкой и ограничением количества результатов

expression: !rql |
  SELECT select(@links.side2, from('current', @linkages_allattributes, @links), where(eq(@links.side1, @doc.id)), order(desc(@links.side1)), limit(1))

В данном выражении вложенный запрос описывает значение, передаваемое в конструкцию SELECT основного запроса:

  • Происходит обращение к связи linkages_allattributes в текущем домене под псевдонимом links.

  • Записи фильтруются по соответствию стороны 1 идентификатору текущего объекта.

  • Результат сортируется по значению стороны 1 в порядке убывания.

  • Количество возвращаемых записей ограничивается одной.

  • Запрос возвращает значение стороны 2 найденной связи.

Таким образом, данное выражение описывает значение по умолчанию для атрибута — первое найденное значение стороны 2 связи linkages_allattributes текущего объекта.

Функция from() может использоваться и в основном запросе. Приведенное выражение равнозначно следующему:

expression: !rql |
  SELECT @links.side2, from('current', @linkages_allattributes, @links) WHERE @links.side1 = @doc.id ORDER BY @links.side1 DESC LIMIT 1

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

Была ли полезна эта страница?

Обратная связь