Как создать JOIN-запрос к HLBlock в Битрикс?

Как правильно выполнить объединение данных из двух highload блоков, чтобы к значениям из одного блока были присоединены цены из второго? В своём коде я использую join, но получаю только массив значений из первой таблицы, без данных из второй. Ниже приведён код, который я написал: 
```php
use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Entity\ReferenceField;
use Bitrix\Main\Entity\Query;

$servicesHLB    = HighloadBlockTable::getById(4)->fetch();
$servicesEntity = HighloadBlockTable::compileEntity($servicesHLB);
$servicesClass  = $servicesEntity->getDataClass();
$pricesHLB      = HighloadBlockTable::getById(6)->fetch();
$pricesEntity   = HighloadBlockTable::compileEntity($pricesHLB);
$pricesClass    = $pricesEntity->getDataClass();
$hlSelect       = array('ID', 'UF_XML_ID', 'UF_NAME', 'UF_TYPE', 'UF_CATEGORY', 'UF_PRICE_LIST', 'UF_SPECIALIZATION');
$hlOrder        = array('UF_NAME' => 'ASC');
$hlFilter       = array('ID' => $rsItem["UF_DIAGNOSTIC_SERVICES"]); // $rsItem["UF_DIAGNOSTIC_SERVICES"] - содержит массив значений
$rsData         = $servicesClass::getList(
    array(
        'select' => $hlSelect,
        'filter' => $hlFilter,
        'runtime' => array(
            new ReferenceField(
                'COST',
                $pricesClass,
                Query\Join::on('this.UF_PRICE_LIST', 'ref.ID')->where('this.UF_PRICE_LIST', true),
                ['join_type' => 'LEFT']
            ),
        ),
        'order' => $hlOrder,
    )
);
if ($hlItem = $rsData->fetchAll()) {
    AddMessage2Log(print_r($hlItem, 1));
}
``` 
Подскажите, в чём может быть ошибка?
  • 20 ноября 2024 г. 14:23
Ответы на вопрос 2
Ваш код выглядит в целом правильно, но в нем может быть несколько моментов, которые стоит проверить, чтобы убедиться, что JOIN выполняется корректно и вы получаете ожидаемые результаты.

1. **Проверьте структуру данных**: Убедитесь, что поле `UF_PRICE_LIST` в вашем высокомасштабируемом блоке services действительно содержит правильные идентификаторы записей из блока prices.

2. **Правильный JOIN**: Убедитесь, что вы правильно используете условия для JOIN. В вашем коде вы используете `where('this.UF_PRICE_LIST', true)` — это может быть скорее всего лишним. Если `UF_PRICE_LIST` не является массивом или не необходимо фильтровать на его основании, вы можете убрать эту часть.

3. **Выбор полей из обеих таблиц**: Убедитесь, что вы выбираете поля из обеих таблиц. Например, добавьте поля из `COST` в ваш `select`:

```php
$hlSelect = array('ID', 'UF_XML_ID', 'UF_NAME', 'UF_TYPE', 'UF_CATEGORY', 'UF_PRICE_LIST', 'UF_SPECIALIZATION', 'COST.UF_PRICE'); // Добавьте цены из COST
```

4. **Проверка наличия данных**: Если данные не появляются, попробуйте вывести запрос в SQL для диагностики. В Битрикс есть функция для получения сгенерированного SQL-запроса:

```php
$query = $servicesClass::getList(array(
    // ваши параметры
));
$query->setQuery('your SQL query');
AddMessage2Log($query->getFinalSql()); // Запись созданного SQL запроса в лог
```

5. **Отладка результата**: Если вы получили результат, но не видите данных из второй таблицы, проверьте ваш массив значений `HLItem`. Убедитесь, что данное значение получено и его структура соответствует ожидаемой.

Попробуйте переписать часть кода с учетом вышеупомянутых советов. Вот пример как может выглядеть ваш код после некоторых корректировок:

```php
use Bitrix\Highloadblock\HighloadBlockTable;
use Bitrix\Main\Entity\ReferenceField;
use Bitrix\Main\Entity\Query;

$servicesHLB    = HighloadBlockTable::getById(4)->fetch();
$servicesEntity = HighloadBlockTable::compileEntity($servicesHLB);
$servicesClass  = $servicesEntity->getDataClass();
$pricesHLB      = HighloadBlockTable::getById(6)->fetch();
$pricesEntity   = HighloadBlockTable::compileEntity($pricesHLB);
$pricesClass    = $pricesEntity->getDataClass();

$hlSelect       = array('ID', 'UF_XML_ID', 'UF_NAME', 'UF_TYPE', 'UF_CATEGORY', 'UF_PRICE_LIST', 'UF_SPECIALIZATION', 'COST.UF_PRICE'); // Добавляем поле UF_PRICE
$hlOrder        = array('UF_NAME' => 'ASC');
$hlFilter       = array('ID' => $rsItem["UF_DIAGNOSTIC_SERVICES"]); // $rsItem["UF_DIAGNOSTIC_SERVICES"] - массив значений

$rsData = $servicesClass::getList(array(
    'select' => $hlSelect,
    'filter' => $hlFilter,
    'runtime' => array(
        new ReferenceField(
            'COST',
            $pricesClass,
            Query\Join::on('this.UF_PRICE_LIST', 'ref.ID'),
            ['join_type' => 'LEFT']
        ),
    ),
    'order' => $hlOrder,
));

if ($hlItem = $rsData->fetchAll()) {
    AddMessage2Log(print_r($hlItem, 1)); // Проверка результата
}
```

Если вы сделали все вышеупомянутое и все еще сталкиваетесь с проблемами, стоит проверить настройки ваших высокомасштабируемых блоков и структуру данных в админке Битрикса.
Потому-что в select нужно указать 'COST.<имя поля из COST>'. Например: 

$hlSelect = array('COST.ID', 'COST.UF_NAME');
Похожие вопросы