Как XQuery превращается в SQL
Введение
Для выполнения запросов можно использовать коробочную функцию XQuery
или функцию tools.xquery
В примерах будем использовать функцию tools.xquery
Всю основную информацию по запросам XQuery
можно найти на портале WebSoft по следующим ссылкам:
- Описание XQuery
- Описание tools.xquery
- Видео с базовым объяснением
- Синтаксис XQuery запросов
- Запросы XQuery
В примерах в блоке XQuery
указан запрос XQuery, выполняющийся через tools.xquery
В примерах в блоке SQL
указан запрос SQL, в который транспилируется запрос XQuery
ядром системы WebSoft
Важно
LuceneFTIndex
отключен, если индекс включен, то некоторые запросы SQL формируются иначе, в запрос подставляются сразу ИД объектов
Запросы
Запрос с выводом полей через запятую
XQuery
SQL
Запрос с выводом полей через Fields(field1, field2)
XQuery
SQL
Запрос с выводом полей через Fields('field1', 'field2')
XQuery
SQL
Запрос к нескольким таблицам с выводом полей из одной таблицы
XQuery
SQL
Запрос к нескольким таблицам с выводом полей из нескольких таблиц
XQuery
Важно
При попытке вывести 2 поля с одинаковым именем из разных таблиц - в результат попадет только одно. Например, return $elem/id, $pos/id
выведет в результат только 1 поле id
SQL
Запрос к нескольким таблицам с выводом полей из нескольких таблиц через Fields()
XQuery
Важно
В запросе XQuery
между Fields
нет запятой. При попытке поставить запятую, запрос выкидывает ошибку
SQL
Запрос к нескольким таблицам с выводом полей из нескольких таблиц через Fields('')
XQuery
Важно
В запросе XQuery
между Fields
нет запятой. При попытке поставить запятую, запрос выкидывает ошибку
SQL
Запрос к нескольким таблицам с переименованием полей
XQuery
Важно
При попытке вывести 2 поля с одинаковым именем из разных таблиц - в результат попадет только одно. Например, return $elem/id, $pos/id
выведет в результат только 1 поле id
SQL
Запрос к нескольким таблицам с переименованием полей через Fields()
XQuery
Важно
При попытке вывести 2 поля с одинаковым именем из разных таблиц - в результат попадет только одно. Например, return $elem/id, $pos/id
выведет в результат только 1 поле id
Важно
В запросе XQuery
между Fields
нет запятой. При попытке поставить запятую, запрос выкидывает ошибку
SQL
Запрос к нескольким таблицам через some/satisfies
XQuery
Важно
При использовании some/satisfies
в результат можно вывести поля только из основного каталога $elem
Важно
Условия в скобках после satisfies
($elem/position_id = $pos/id)
будут перенесены в ON
к INNER JOIN
, все условия после скобок будут перенесены в WHERE
SQL
Запрос к трём и более таблицам через some/satisfies
XQuery
Важно
При использовании some/satisfies
в результат можно вывести поля только из основного каталога $elem
Важно
Условия в скобках после satisfies
($elem/position_id = $pos/id)
будут перенесены в ON
к INNER JOIN
, все условия после скобок будут перенесены в WHERE
Важно
Обратите внимание на порядок some/satisfies
в XQuery
запросе и в каком порядке они оказались собраны в SQL
запросе. Если поменяем строки местами, то получим ошибку в SQL запросе
SQL
select t_elem.[id],
t_elem.[position_name]
from dbo.[collaborators] t_elem
where t_elem.[id] in (
select t_elem.[id]
from dbo.[collaborators] t_elem
inner join dbo.[positions] t_pos ON t_elem.[position_id] = t_pos.[id]
inner join dbo.[appointment_types] t_app ON t_pos.[position_appointment_type_id] = t_app.[id]
where t_pos.[name] = 'Тренер'
)
select t_elem."id",
t_elem."position_name"
from dbo."collaborators" t_elem
where t_elem."id" in (
select t_elem."id"
from dbo."collaborators" t_elem
inner join dbo."positions" t_pos ON t_elem."position_id"= t_pos."id"
inner join dbo."appointment_types" t_app ON t_pos."position_appointment_type_id"= t_app."id"
where t_pos."name"='Тренер'
)
order by t_elem.id
Запрос с поиском через contains
XQuery
SQL
Запрос с поиском через doc-contains
Важно
Поиск через doc-contains
производится с начала слова, то есть, если в карточке сотрудника в поле position_name
будет указана должность Тренер
, поиск по фразе трен
найдет всех тренеров, поиск по фразе ренер
не найдет тренеров
XQuery
SQL
Запрос с поиском по кастомному полю через doc-contains
XQuery
Важно
Название поля и значение автоматически оборачиваются в кавычки, что можно наблюдать в полученном запросе SQL
Важно
Поиск через doc-contains
производится с начала слова, то есть, если в карточке сотрудника в поле position_name
будет указана должность Тренер
, поиск по фразе трен
найдет всех тренеров, поиск по фразе ренер
не найдет тренеров
SQL
Запрос с поиском по кастомному полю через doc-contains и contains по значению
XQuery
Важно
Название поля и значение автоматически оборачиваются в кавычки, что можно наблюдать в полученном запросе SQL
Важно
Поиск через doc-contains
производится с начала слова, то есть, если в карточке сотрудника в поле position_name
будет указана должность Тренер
, поиск по фразе трен
найдет всех тренеров, поиск по фразе ренер
не найдет тренеров
SQL
Запрос с поиском по кастомному полю через doc-contains с приведением типов
XQuery
SQL
Запрос с использованием ForeignElem
XQuery
SQL
Запрос с использованием true(), false(), null(), ''
XQuery
SQL
select t_elem.[id], t_elem.[fullname]
from dbo.[collaborators] t_elem
where (t_elem.[is_dismiss] = 0 OR t_elem.[is_dismiss] IS NULL) or -- $elem/is_dismiss = false()
t_elem.[is_dismiss] <> 0 or -- $elem/is_dismiss != false()
t_elem.[is_dismiss] = 1 or -- $elem/is_dismiss = true()
(t_elem.[is_dismiss] <> 1 OR t_elem.[is_dismiss] IS NULL) or -- $elem/is_dismiss != true()
t_elem.[is_dismiss] IS NULL or -- $elem/is_dismiss = null()
t_elem.[is_dismiss] IS NOT NULL or -- $elem/is_dismiss != null()
t_elem.[is_dismiss] IS NULL or -- $elem/is_dismiss = ''
t_elem.[is_dismiss] IS NOT NULL -- $elem/is_dismiss != ''
select t_elem."id",
t_elem."fullname"
from dbo."collaborators" t_elem
where ((t_elem."is_dismiss"=false) OR ((t_elem."is_dismiss") IS NULL))
or t_elem."is_dismiss"<>false
or t_elem."is_dismiss"=true
or ((t_elem."is_dismiss"<>true) OR ((t_elem."is_dismiss") IS NULL))
or t_elem."is_dismiss" IS NULL
or t_elem."is_dismiss" IS NOT NULL
or t_elem."is_dismiss" IS NULL
or t_elem."is_dismiss" IS NOT NULL
order by t_elem.id
Запрос с использованием date()
XQuery
SQL
Запрос иерархии с использованием IsHierChild()
Важно
Перед функцией IsHierChild
обязательно должен стоять пробел, знак табуляции приводит к ошибке
Важно
Не работает через XQuery
XQuery
SQL
WITH [subdivisions_cte] (
[id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
[__hlevel],
[__sort_level],
[__hcc]
) AS (
SELECT [id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
0 as [__hlevel],
cast((CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select top 1 1 from dbo.[subdivisions] f where f.parent_object_id = e.id) as [__hcc]
FROM dbo.[subdivisions] e
WHERE e.parent_object_id = 6327975429225669221
UNION ALL
SELECT e.[id],
e.[code],
e.[name],
e.[org_id],
e.[parent_object_id],
e.[is_disbanded],
e.[knowledge_parts],
e.[tags],
e.[experts],
e.[place_id],
e.[region_id],
e.[kpi_profile_id],
e.[bonus_profile_id],
e.[cost_center_id],
e.[is_faculty],
e.[modification_date],
e.[app_instance_id],
e.[kpi_profiles_id],
[__hlevel] + 1,
cast((d.[__sort_level] + '.' + CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select 1 WHERE EXISTS (SELECT id FROM dbo.[subdivisions] f WHERE e.id = f.parent_object_id)) as [__hcc]
FROM dbo.[subdivisions] e
INNER JOIN [subdivisions_cte] d ON e.parent_object_id = d.id
)
select t_elem.[id],
[__hcc],
[__hlevel]
from [subdivisions_cte] t_elem
order by t_elem.[__sort_level] asc
WITH RECURSIVE "subdivisions_cte" (
"id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags",
"experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
"__hlevel",
"__sort_level",
"__hcc"
) AS (
SELECT "id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags","experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
0 as __hlevel,
cast((CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 from dbo."subdivisions" f where f.parent_object_id = e.id limit 1) as "__hcc"
FROM dbo."subdivisions" e
WHERE e.parent_object_id = '6327975429225669221'
UNION ALL
SELECT e."id",
e."code",
e."name",
e."org_id",
e."parent_object_id",
e."is_disbanded",
e."knowledge_parts",
e."tags",
e."experts",
e."place_id",
e."region_id",
e."kpi_profile_id",
e."kpi_profiles_id",
e."bonus_profile_id",
e."cost_center_id",
e."is_faculty",
e."modification_date",
e."app_instance_id","__hlevel"+1,
cast((d."__sort_level"||'.'||CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 WHERE EXISTS (SELECT id FROM dbo."subdivisions" f WHERE e.id = f.parent_object_id)) as "__hcc"
FROM dbo."subdivisions" e
INNER JOIN "subdivisions_cte" d ON e.parent_object_id = d.id
)
select t_elem."id",
t_elem."name",
"__hcc",
"__hlevel"
from "subdivisions_cte" t_elem
order by t_elem."__sort_level" asc nulls first
Запрос иерархии с использованием IsHierChildOrSelf()
Важно
Перед функцией IsHierChild
обязательно должен стоять пробел, знак табуляции приводит к ошибке
Важно
Не работает через XQuery
XQuery
SQL
WITH [subdivisions_cte] (
[id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
[__hlevel],
[__sort_level],
[__hcc]
) AS (
SELECT [id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
0 as [__hlevel],
cast((CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select top 1 1 from dbo.[subdivisions] f where f.parent_object_id = e.id) as [__hcc]
FROM dbo.[subdivisions] e
WHERE e.id = 6327975429225669221
UNION ALL
SELECT e.[id],
e.[code],
e.[name],
e.[org_id],
e.[parent_object_id],
e.[is_disbanded],
e.[knowledge_parts],
e.[tags],
e.[experts],
e.[place_id],
e.[region_id],
e.[kpi_profile_id],
e.[bonus_profile_id],
e.[cost_center_id],
e.[is_faculty],
e.[modification_date],
e.[app_instance_id],
e.[kpi_profiles_id],
[__hlevel] + 1,
cast((d.[__sort_level] + '.' + CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select 1 WHERE EXISTS (SELECT id FROM dbo.[subdivisions] f WHERE e.id = f.parent_object_id)) as [__hcc]
FROM dbo.[subdivisions] e
INNER JOIN [subdivisions_cte] d ON e.parent_object_id = d.id
)
select t_elem.[id],
t_elem.[name],
[__hcc],
[__hlevel]
from [subdivisions_cte] t_elem
where (( t_elem.[is_disbanded] = 0) OR (( t_elem.[is_disbanded]) IS NULL))
order by t_elem.[__sort_level] asc
WITH RECURSIVE "subdivisions_cte" (
"id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags",
"experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
"__hlevel",
"__sort_level","__hcc"
) AS (
SELECT "id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags",
"experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
0 as __hlevel,
cast((CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 from dbo."subdivisions" f where f.parent_object_id = e.id limit 1) as "__hcc"
FROM dbo."subdivisions" e
WHERE e.id = '6327975429225669221'
UNION ALL
SELECT e."id",
e."code",
e."name",
e."org_id",
e."parent_object_id",
e."is_disbanded",
e."knowledge_parts",
e."tags",
e."experts",
e."place_id",
e."region_id",
e."kpi_profile_id",
e."kpi_profiles_id",
e."bonus_profile_id",
e."cost_center_id",
e."is_faculty",
e."modification_date",
e."app_instance_id",
"__hlevel"+1,
cast((d."__sort_level"||'.'||CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 WHERE EXISTS (SELECT id FROM dbo."subdivisions" f WHERE e.id = f.parent_object_id)) as "__hcc"
FROM dbo."subdivisions" e
INNER JOIN "subdivisions_cte" d ON e.parent_object_id = d.id
)
select t_elem."id",
t_elem."name",
"__hcc",
"__hlevel"
from "subdivisions_cte" t_elem
where (( t_elem."is_disbanded"=false) OR (( t_elem."is_disbanded") IS NULL))
order by t_elem."__sort_level" asc nulls first
Запрос с использованием MatchSome()
XQuery
SQL
Запрос с использованием CatalogHierSubset()
XQuery
SQL
WITH [subdivisions_cte] (
[id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
[__hlevel],
[__sort_level],
[__hcc]
) AS (
SELECT [id],
[code],
[name],
[org_id],
[parent_object_id],
[is_disbanded],
[knowledge_parts],
[tags],
[experts],
[place_id],
[region_id],
[kpi_profile_id],
[bonus_profile_id],
[cost_center_id],
[is_faculty],
[modification_date],
[app_instance_id],
[kpi_profiles_id],
0 as [__hlevel],cast((CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select top 1 1 from dbo.subdivisions f where f.parent_object_id = e.id) as [__hcc]
FROM dbo.subdivisions e
WHERE parent_object_id = 6327975429225669221
UNION ALL
SELECT e.[id],
e.[code],
e.[name],
e.[org_id],
e.[parent_object_id],
e.[is_disbanded],
e.[knowledge_parts],
e.[tags],
e.[experts],
e.[place_id],
e.[region_id],
e.[kpi_profile_id],
e.[bonus_profile_id],
e.[cost_center_id],
e.[is_faculty],
e.[modification_date],
e.[app_instance_id],
e.[kpi_profiles_id],
[__hlevel] + 1,
cast((d.[__sort_level] + '.' + CAST(FLOOR(LOG10(ROW_NUMBER() over(order by e.id))) as varchar) + cast(ROW_NUMBER() over(order by e.id) as varchar(256))) as varchar(256)) as [__sort_level],
(select 1 WHERE EXISTS (SELECT id FROM dbo.subdivisions f WHERE e.id = f.parent_object_id)) as [__hcc]
FROM dbo.subdivisions e
INNER JOIN [subdivisions_cte] d ON e.parent_object_id = d.id
)
select t_x.*
from [subdivisions_cte] t_x
WITH RECURSIVE "subdivisions_cte" (
"id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags","experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
"__hlevel",
"__sort_level",
"__hcc"
) AS (
SELECT "id",
"code",
"name",
"org_id",
"parent_object_id",
"is_disbanded",
"knowledge_parts",
"tags",
"experts",
"place_id",
"region_id",
"kpi_profile_id",
"kpi_profiles_id",
"bonus_profile_id",
"cost_center_id",
"is_faculty",
"modification_date",
"app_instance_id",
0 as "__hlevel",
cast((CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 from dbo.subdivisions f where f.parent_object_id = e.id limit 1) as "__hcc"
FROM dbo.subdivisions e
WHERE parent_object_id = '6327975429225669221'
UNION ALL
SELECT e."id",
e."code",
e."name",
e."org_id",
e."parent_object_id",
e."is_disbanded",
e."knowledge_parts",
e."tags",
e."experts",
e."place_id",
e."region_id",
e."kpi_profile_id",
e."kpi_profiles_id",
e."bonus_profile_id",
e."cost_center_id",
e."is_faculty",
e."modification_date",
e."app_instance_id",
"__hlevel"+1,
cast((d."__sort_level"||'.'||CAST(FLOOR(LOG(ROW_NUMBER() over(order by e."id"))) as varchar)||cast(ROW_NUMBER() over(order by e."id") as varchar(256))) as varchar(256)) as "__sort_level",
(select 1 WHERE EXISTS (SELECT id FROM dbo.subdivisions f WHERE e.id = f.parent_object_id)) as "__hcc"
FROM dbo.subdivisions e
INNER JOIN "subdivisions_cte" d ON e.parent_object_id = d.id
)
select t_x.*
from "subdivisions_cte" t_x
Запрос с использованием IsEmpty()
XQuery
SQL
Запрос к нескольким таблицам через ljoin/on (LEFT JOIN)
Важно
Обратите внимание на порядок таблиц в XQuery
запросе и в каком порядке они оказались собраны в SQL
запросе, ljoin
джойнит правую таблицу collaborators
к левой positions
XQuery
SQL
Запрос к нескольким таблицам через rjoin/on (RIGHT JOIN)
Важно
Обратите внимание на порядок таблиц в XQuery
запросе и в каком порядке они оказались собраны в SQL
запросе, rjoin
джойнит правую таблицу collaborators
к левой positions
XQuery
SQL
Запрос к нескольким таблицам через join/on (INNER JOIN)
Важно
Обратите внимание на порядок таблиц в XQuery
запросе и в каком порядке они оказались собраны в SQL
запросе, join
джойнит правую таблицу collaborators
к левой positions
Важно
Обратите внимание, что в запросе XQuery
между Fields
нет запятой. При попытке поставить запятую, запрос выкидывает ошибку
XQuery
SQL
Запрос с исключением записей через MatchSome
Важно
Обратите внимание на порядок таблиц в XQuery
запросе и в каком порядке они оказались собраны в SQL
запросе, ljoin
джойнит правую таблицу collaborators
к левой collaborators
XQuery
SQL
Запрос с формированием уникального списка DISTINCT
XQuery
Важно
Работает только в том случае, когда в запросе XQuery
возвращается только одно поле, по которому нужна уникальность
Важно
Для корректной работы необходимо явно указать сортировку order by
по одному из выводимых полей. Проблема в том, что по умолчанию в запрос всегда добавляется сортировка order by t_elem.id
, но в запросе выводятся другие поля, что приводит к ошибке.
SQL