R
R
ragnar_ok2019-11-17 13:52:12
1C-Bitrix
ragnar_ok, 2019-11-17 13:52:12

Bitrix ORM: How to get items with zero CNT?

There is an infoblock with apartments, an infoblock with layouts and an infoblock with houses. The connection with the "Binding to infoblock elements" property goes from apartments to layouts and from layouts to houses. You need to get all the houses that have all the apartments "ACTIVE" => "N".
To do this, I created the following Query object:

$queryObj = ElementTable::query()
    ->where([
        ['IBLOCK.CODE', 'apartments'], ['ACTIVE', 'Y'], // получаю только активные элементы из инфоблока "Квартиры"
        ['APARTMENT_PROPERTY.CODE', 'LAYOUTS_ID'], // получаю только свойство с кодом LAYOUTS_ID (привязка к эл. инфоблока "Квартиры")
        ['LAYOUT_PROPERTY.CODE', 'COMPLEX_ID'], // получаю только свойство с кодом COMPLEX_ID (привязка к эл. инфоблока "Планировки")
    ])

    ->registerRuntimeField(new Reference( // получаю таблицу свойств инфоблока "Квартиры"
        'APARTMENT_PROPERTY',
        PropertyTable::class,
        Join::on('this.APARTMENT_ELEMENT_PROPERTY.IBLOCK_PROPERTY_ID', 'ref.ID')
    ))
    ->registerRuntimeField(new Reference( // получаю таблицу значений свойств инфоблока "Квартиры"
        'APARTMENT_ELEMENT_PROPERTY',
        ElementPropertyTable::class,
        Join::on('this.ID', 'ref.IBLOCK_ELEMENT_ID')
    ))

    ->registerRuntimeField(new Reference( // получаю таблицу элементов инфоблока "Планировки"
        'LAYOUT',
        ElementTable::class,
        Join::on('this.APARTMENT_ELEMENT_PROPERTY.VALUE', 'ref.ID')
    ))
    ->registerRuntimeField(new Reference( // получаю таблицу свойств инфоблока "Планировки"
        'LAYOUT_PROPERTY',
        PropertyTable::class,
        Join::on('this.LAYOUT_ELEMENT_PROPERTY.IBLOCK_PROPERTY_ID', 'ref.ID')
    ))
    ->registerRuntimeField(new Reference( // получаю таблицу значений свойств инфоблока "Планировки"
        'LAYOUT_ELEMENT_PROPERTY',
        ElementPropertyTable::class,
        Join::on('this.LAYOUT.ID', 'ref.IBLOCK_ELEMENT_ID')
    ))

    ->addSelect('LAYOUT_ELEMENT_PROPERTY.VALUE', 'COMPLEX_ID') // получаю ID домов с активными квартирами. Указываю alias "COMPLEX_ID"
    ->addSelect(new ExpressionField('CNT', 'COUNT(%s)', 'LAYOUT_ELEMENT_PROPERTY.VALUE')) // считаю количество активных квартир
;

var_dump($queryObj->fetchAll());

It seems to me that it would be better to get a filter on CNT => 0 . But the problem is that in the results there is no house with CNT => 0 due to the fact that I have a filter by ACTIVE => N. How can I solve this problem?
Accordingly request:
SELECT 
  `iblock_element_layout_element_property`.`VALUE` AS `COMPLEX_ID`,
  COUNT(`iblock_element_layout_element_property`.`VALUE`) AS `CNT`
FROM `b_iblock_element` `iblock_element` 
LEFT JOIN `b_iblock_element_property` `iblock_element_apartment_element_property` ON `iblock_element`.`ID` = `iblock_element_apartment_element_property`.`IBLOCK_ELEMENT_ID`
LEFT JOIN `b_iblock_property` `iblock_element_apartment_property` ON `iblock_element_apartment_element_property`.`IBLOCK_PROPERTY_ID` = `iblock_element_apartment_property`.`ID`
LEFT JOIN `b_iblock_element` `iblock_element_layout` ON `iblock_element_apartment_element_property`.`VALUE` = `iblock_element_layout`.`ID`
LEFT JOIN `b_iblock_element_property` `iblock_element_layout_element_property` ON `iblock_element_layout`.`ID` = `iblock_element_layout_element_property`.`IBLOCK_ELEMENT_ID`
LEFT JOIN `b_iblock_property` `iblock_element_layout_property` ON `iblock_element_layout_element_property`.`IBLOCK_PROPERTY_ID` = `iblock_element_layout_property`.`ID`
LEFT JOIN `b_iblock` `iblock_element_iblock` ON `iblock_element`.`IBLOCK_ID` = `iblock_element_iblock`.`ID`
WHERE `iblock_element_iblock`.`CODE` = 'apartments' AND `iblock_element`.`ACTIVE` = 'Y' AND `iblock_element_apartment_property`.`CODE` = 'LAYOUTS_ID' AND `iblock_element_layout_property`.`CODE` = 'COMPLEX_ID'
GROUP BY `iblock_element_layout_element_property`.`VALUE`

https://pastebin.com/Z91qLDQb

Answer the question

In order to leave comments, you need to log in

1 answer(s)
G
Georgy Baruchyan, 2019-11-17
@ragnar_ok

If I understood everything correctly, then you need to modify one of the runtimes a little.
I will give an example from my code, try to adapt it to yours:

->registerRuntimeField('PRICE', [
                'data_type' => \Bitrix\Catalog\PriceTable::class,
                'reference' => [
                    '=this.ID' => 'ref.PRODUCT_ID',
                    '=ref.CATALOG_GROUP_ID' => new \Bitrix\Main\DB\SqlExpression('?', 1)
                ]
            ])

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question