Использование вложенных запросов и CTE для работы с объектами доменов
В данном разделе описан синтаксис вложенных запросов и общих табличных выражений (CTE) при настройке правил данных и политик доступа.
|
В данном разделе при описании RQL-выражений приняты следующие соглашения:
|
Использование промежуточных вычислений (SELECT())
Функция SELECT() используется для выполнения вложенного запроса или промежуточного вычисления, и получения его результата в месте вызова. Такой запрос рассматривается как выражение и возвращает значение, которое можно использовать в основном запросе.
Функция select() поддерживает следующие конструкции, переданные как аргументы:
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)
В данном запросе:
-
Формируется вложенный запрос, которому присваивается псевдоним
sub_query. -
Во вложенном запросе в качестве источника используется связь
linkages_allattributesв текущем домене под псевдонимомlinks. -
Выполняется соединение экземпляров связи с текущим объектом. Соединение определяется равенством стороны 1 связи и идентификатора текущего объекта.
-
Применяется фильтрация: в выборку попадают только те экземпляры связи, у которых значение атрибута
weightбольше 100. -
Результат сортируется по стороне 1 связи в порядке убывания.
-
Выборка ограничивается одной записью.
-
Из выборки возвращается значение стороны связи 2.
-
В основном запросе используется результат вложенного запроса
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)
Примеры использование вложенных запросов
Использование вложенного запроса и функции from() для фильтрации
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
В данном случае операции с выборкой задаются в основном запросе.
Была ли полезна эта страница?