Yandex Metrika
sanches.free

Вычисляемые поля ORM в Bitrix D7: агрегаты и функции SQL в запросе

Зачем смешивать SQL с ORM

Иногда в одном запросе нужно и отфильтровать живые столбцы сущности, и получить производные значения вида суммы или крайней даты. В D7 это делают через массив runtime у getList(): туда добавляют поля-представления, которые не живут как отдельные колонки в таблице, но становятся частью отправляемого SQL.

Плейсхолдер и список полей для подстановки

Класс \Bitrix\Main\ORM\Fields\ExpressionField (в старших проектах встречается устаревшее совместимое имя Entity\ExpressionField) принимает машинное имя псевдополя, шаблон SQL и имена столбцов карты таблицы, которые платформа аккуратно экранирует и подставляет вместо %s.

Самый частый паттерн: MIN и MAX без группировки

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

$userBounds = \Bitrix\Main\UserTable::getList([
    'filter' => ['=ACTIVE' => 'Y'],
    'runtime' => [
        new \Bitrix\Main\ORM\Fields\ExpressionField(
            'BIRTHDAY_MIN',
            'MIN(%s)',
            ['PERSONAL_BIRTHDAY']
        ),
        new \Bitrix\Main\ORM\Fields\ExpressionField(
            'BIRTHDAY_MAX',
            'MAX(%s)',
            ['PERSONAL_BIRTHDAY']
        ),
    ],
    'select' => ['BIRTHDAY_MIN', 'BIRTHDAY_MAX'],
]);
$edgeDates = $userBounds->fetch();

Размер результата — одна строка с двумя псевдостолбцами; платформа знает типы и приведёт календарные поля к объекту \Bitrix\Main\Type\Date там, где это предусмотрено картой UserTable.

Что ещё удобно выражать тем же способом

На практике к набору SUM(%s), COUNT(*), LENGTH(%s), приведение регистра LOWER(%s) или конкатенацию двух столбцов подключают, когда хотят не дублировать текст SQL в строковых константах вне объектной обёртки ядра. Для простых производных между двумя известными полями стоит сохранять читаемый шаблон и список полей синхронно с обновлениями таблицы, иначе рефакторинг мапперов затронет несколько точек приложения.

Ограничения и производительность

  • «Тяжёлые» агрегаты по большим наборам лучше сопровождать осмысленным filter, индексами по столбцам из выражений и пониманием того, нужна ли здесь именно строка результата в стиле ORM или отдельный «сырой» отчёт.
  • Если в одном запросе несколько конфликтующих GROUP BY на уровне логики, проще вернуться к явному тексту через Query или разбить сценарий на два узких запроса, чем плотить недокументируемые вложения в runtime.
  • Всегда проверяйте SQL на копии: конструктор синтаксиса не заменяет профилировщик базы под ваш профиль данных.

Не хотите копаться сами?

Починю за 1-3 дня. Без предоплаты — оплата по результату.

15+ лет опыта с 1С-Битрикс · Без предоплаты · 7 дней гарантии