Для разработчиков
Запросы
Запрос в Интеграме — сохранённое декларативное определение: какие колонки, из каких таблиц, с какими условиями, функциями и итогами. Ядро компилирует его в SQL при каждом вызове, а путь между таблицами находит само по метаданным — писать JOIN вручную не нужно.
Один и тот же запрос отдаёт человеку HTML-отчёт, коду — JSON по тому же адресу, ИИ-агенту — данные через MCP; фильтры, сортировка и состав колонок управляются параметрами адреса. Создание запросов командами API разобрано в справочнике API (/api.html#reports), запись данных запросом — на странице «Хранимые процедуры».
Примеры даны для https://ideav.ru и базы mydb; токен в примерах передаётся как в справочнике API — заголовком X-Authorization вместе с параметром JSON.
Что такое запрос
Запрос и его колонки
Запрос — запись таблицы 22, его колонки — записи таблицы 28 с up={id запроса}. У колонки есть источник (таблица или колонка), «Имя в отчёте», функция, фильтр и сортировка; полный разбор полей — в справочнике API (/api.html#report-model).
- Первая колонка задаёт главную таблицу: строки отчёта — её записи.
- Колонки связанных таблиц добавляются просто id их колонок — путь по ссылкам ядро находит само (см. «Соединения по метаданным»).
GROUP BYстроится по всем видимым колонкам без функции.- Определение запроса — записи той же базы: запрос создаётся и правится тем же API, что и данные, без выкладки кода, и переносится между базами JSON-файлом.
Адрес вызова
Запрос вызывается командой report — по id или по названию, в адресе регистр не важен: report/intReports и report/intreports — один запрос.
curl -s -H "X-Authorization: $TOKEN" "https://ideav.ru/mydb/report/950?JSON_KV"
curl -s -H "X-Authorization: $TOKEN" "https://ideav.ru/mydb/report/Клиенты%20по%20категориям?JSON_KV&FR_Категория=Клиент"
Без параметра JSON (или JSON_KV, JSON_DATA…) запрос считается переходом браузера и уходит на страницу входа — токен в заголовке тогда не читается.
Форматы ответа
Четыре формата — один адрес
| Формат | Что отдаёт | Кому |
|---|---|---|
| — (по умолчанию) | HTML-страницу отчёта | человеку в браузере |
JSON_KV | Массив объектов; ключи — «Имя в отчёте» (t100) | интерфейсам и скриптам |
JSON_DATA | Данные первой строки | скалярные выборки «одна запись» |
JSON | Строки плюс метаданные: тип, формат и права каждой колонки | внешним клиентам, которые форматируют сами |
Даты приходят unix-секундами — метаданные формата из JSON подсказывают, как их показать. Пример ответа JSON_KV — в справочнике API (/api.html#report-run).
Заголовки X-Query-Id и X-Query-Name
Каждый ответ помечается заголовками X-Query-Id и X-Query-Name. Потребитель — дашборд, скрипт, внешняя система — записывает, на каком именно запросе построены его данные: когда определение поменяют, расхождение находится по источнику, а не по симптомам.
Параметры адреса
Фильтры FR_ и TO_
Внешние фильтры передаются по «Имени в отчёте» (t100): FR_{имя} — от, TO_{имя} — до; пробелы в имени заменяются на _. Они перекрывают постоянные фильтры колонок (t102/t103) и работают только на колонках с заполненным именем — колонка без имени снаружи не фильтруется (см. «Права и ограничители»).
# срез за октябрь, первые 50 строк
curl -s -H "X-Authorization: $TOKEN" "https://ideav.ru/mydb/report/951?JSON_KV&FR_Дата=01.10.2026&TO_Дата=31.10.2026&LIMIT=50"
# то же в ссылке для человека: страница отчёта откроется уже отфильтрованной
# https://ideav.ru/mydb/report/951?FR_Дата=01.10.2026&TO_Дата=31.10.2026
Сортировка, пагинация, итоги и состав колонок
| Параметр | Что делает |
|---|---|
ORDER={id колонки} | Сортировка; минус перед id — по убыванию |
LIMIT=N | Ограничение числа строк (пагинация) |
RECORD_COUNT | Вернуть только число строк |
SELECT=имя:ФУНКЦИЯ | Состав колонок поверх сохранённого |
TOTALS=имя:SUM | Итог по колонке в ответе |
Определение при этом не меняется: один сохранённый запрос обслуживает и полный отчёт, и узкий срез под конкретного потребителя.
Встроенные переменные и _request_
В фильтрах определения (t102/t103) и в формулах работают встроенные переменные; их значения подставляются при каждом вызове.
| Переменная | Значение |
|---|---|
[TODAY], [NOW], [YESTERDAY], [WEEK_AGO], [MONTH_AGO] | Относительные даты |
[USER], [USER_ID] | Текущий пользователь, его id |
[ROLE], [ROLE_ID] | Роль вызывающего |
_request_.Имя | Параметр адреса: report/950?ProjID=12 читается как _request_.ProjID |
[Имя запроса] | Значение другого запроса (подзапрос) |
Например, скрытая колонка «Ответственный» с фильтром t102=[USER_ID] делает запрос «только свои строки» для каждого вызывающего — и её нельзя перекрыть из адреса, если у неё нет имени в отчёте.
Язык фильтров
Что можно писать в фильтре
Фильтр — не только значение: язык условий один и тот же в t102/t103, в FR_/TO_ и в условии колонки.
| Значение | Отбирает |
|---|---|
Одобрена | Равно значению; у справочной колонки — по названию записи |
660 при t104=abn_ID | Ссылка на запись справочника 660 |
%…% | Маска: подстрока в любом месте |
% / !% | Непусто / пусто |
!1 | Не равно |
IS NULL | Нет значения |
IN(1;2;3) | Вхождение в список |
~шаблон | Регулярное выражение |
1.1 и TO_=31.12 | Диапазон: от и до |
[Имя запроса] | Подзапрос в условии |
Индекс по значению префиксный: маска с % в начале строки (%Иванов) его не использует — на больших таблицах такой фильтр перебирает строки.
Соединения по метаданным
Как ядро находит путь
Пользователь выбирает колонки, ядро само находит путь между таблицами и строит LEFT JOIN без единого условия, написанного рукой. Пути, по которым идёт автосоединение:
- ссылка «на нас» — колонка главной таблицы указывает на другую таблицу;
- ссылка «от нас» — другая таблица ссылается на главную;
- подчинённая таблица — записи с
upна запись главной; - родитель — переход к таблице владельца.
Несколько ссылок и явный JOIN
Если на одну таблицу ведут несколько ссылок, соединение выбирается по тому, какая ссылочная колонка стоит в отчёте. Подключить таблицу дважды или соединить по произвольному условию можно явным JOIN с псевдонимом.
Производные таблицы: агрегаты не размножаются
Каждая присоединённая таблица, внутри которой агрегат, оформляется производной таблицей со своей группировкой. Поэтому «сумма заявок по компании» не размножается её договорами: соединение считает агрегат отдельно и подставляет готовое значение.
Цепочки одного уровня (Компания ← Заявка ← Договор) так не спасаются — суммы с разных уровней удваиваются. Их считают подзапросами, см. «Подзапросы и рекурсия».
Подзапросы и рекурсия
Сохранённый запрос как подзапрос
Любой сохранённый запрос вкладывается в другой конструкцией [Имя запроса] — в формуле колонки, фильтре, ORDER BY, GROUP BY или HAVING — без ограничения глубины.
Подзапрос без строк возвращает пусто — оберните его в IFNULL(…, 0) или задайте запросу «Если пусто, вернуть» (t113=0). Развёрнутый пример с суммами по цепочке Компания ← Заявка ← Договор — в справочнике API (/api.html#report-subquery).
RECURSIVE: оба вида иерархий
Функция RECURSIVE у первой колонки превращает запрос в рекурсивный CTE. Она умеет оба вида иерархий:
- дерево по ссылке таблицы на саму себя: «все подразделения ниже данного», категории, BOM;
- дерево подчинённых записей: «все пункты меню, доступные роли».
Результат возвращается множеством id и вкладывается в другие запросы подзапросом — рекурсивная часть пишется один раз, а используется везде.
Права и ограничители
Чьи права действуют
Запрос работает как хранимая процедура: с правами того, кто его настроил, а не того, кто вызывает. Роли вызывающего нужен только доступ READ к самому запросу — он открывает все колонки и строки, которые отбирает запрос; доступы роли к таблицам и её маски при этом не применяются.
Это не обход прав, а назначение запроса: отдать ровно то, что решил аналитик, в том числе из таблиц, которые роль руками не видит. Внешняя система, которой выдан доступ к одному запросу, видит только его результат и не открывает таблицы.
Фильтруемость — только по имени
- Снаружи фильтруются только колонки с заполненным «Именем в отчёте»:
FR_/TO_перекрывают их постоянные фильтры. - У колонки без имени фильтр параметрами адреса не переопределяется — защита от подмены фильтра вызывающим.
- Фильтруемость включается явно: всё, чему аналитик не дал имени, закрыто. Это строже правила «фильтровать можно всё, кроме запрещённого».
Не давайте колонке-ограничителю «Имя в отчёте»: с именем её фильтр становится параметром, и вызывающий подставит в FR_ чужой id вместо [USER_ID]. Запись данных запросом и полный разбор прав — на странице Хранимые процедуры →
Кто вызывает запрос
Ссылки и внешний планировщик
Адрес отчёта — прямой вызов из браузера или HTTP-клиента. Диапазон дат и отбор передаются параметрами адреса, поэтому «готовый срез» — это ссылка, а не инструкция. Внешняя система забирает данные по расписанию тем же адресом — например, Airflow при выгрузке в хранилище: report/17021?JSON_KV.
Кнопки в таблицах
Кнопка-колонка вызывает запрос с подстановками из строки — [ID], значения колонок, — поэтому «открыть срез по этой записи» настраивается одной кнопкой. Триггеры и подстановки — на странице Триггеры кнопок →
Дашборды и ИИ-агенты
- Панели дашбордов и сводные таблицы питаются теми же запросами — без отдельного коннектора с кэшем.
- MCP-сервер integram-mcp отдаёт агенту инструменты отчётов: выполнение, чтение структуры, создание, колонки, клонирование, умный и естественный поиск нужного запроса.
- ИИ-чат строит ответ на своём запросе в той же базе.
Агент работает с данными с правами пользователя, от имени которого вызван, — отдельных «агентских» доступов выдавать не нужно.
Лимиты и производительность
Время и объём
- Запрос ограничен по времени: 30 секунд по умолчанию, до 600; зависшее выполнение снимается принудительно.
- Списки пагинированы; потолок строк можно задать в самом определении.
- Выборочный запрос — по ключу, родителю, ссылке — по размеру ответа, а не базы, и не зависит от числа соединений: каждое идёт по индексу.
- Тяжёлая агрегация по миллионам строк растёт с объёмом: на замере 1 млн транзакций по 45 реквизитам сумма за 90 дней — 28 с на EAV «как есть» и 4,7 с с разрезом и накопителями; карточка по ключу — 3 мс.
Для чистой аналитики больших объёмов штатный путь — накопители или выгрузка в DWH тем же запросом в JSON. Обзор «что умеет движок» с примерами из проектов — в статье Запросы Интеграма (база знаний №28) →