Всем привет.
Сегодня коллеги озвучили задачу:
Необходимо выбрать все элементы инфоблока у которых дублируются символьные коды. Да так чтоб и идентификаторы элементов в этом же запросе выбрались.Т.е. нужно всё выбрать одним запросом. А потом уже обновить коды у элементов.Я говорю: "Да, легко!", и пишу запрос:
sel ect
CODE, COUNT(ID) as CNT, GROUP_CONCAT(ID) as IDList
fr om
b_iblock_element
WHERE
IBLOCK_ID = 1
GROUP BY CODE
HAVING CNT > 1
|
Ребята говорят: "Клёво, конечно, но не по феншую! Надо бы на API."
Тут мы вспоминаем про D7, DataManager и registerRuntimeField. Даже показывают куски кода с попыткой решения задачи.
Мы добавляем туда 1 строку и задача решена!
CModule::IncludeModule('iblock');
$query = new \Bitrix\Main\Entity\Query(Bitrix\Iblock\ElementTable::getEntity());
$query
->setSelect(array('CODE', 'cnt', 'IDList'))
->setFilter(array('IBLOCK_ID' => 1, '>cnt' => 1))
->registerRuntimeField('cnt', array(
'data_type' => 'integer',
'expression' => array('count(%s)', 'CODE')
))
->registerRuntimeField('IDList', array(
'data_type' => 'string',
'expression' => array('GROUP_CONCAT(%s)', 'ID')
)
);
$obResult = $query->exec();
print($query->getQuery())."\r\n";
print_r($obResult->fetchall());
|
В результате получаем массив вида
Array
(
[0] => Array
(
[CODE] => news
[cnt] => 3
[IDList] => 1,2,3
)
) |
А запрос API сгенерировало такой же как и у меня практически
SELECT
`iblock_element`.`CODE` AS `CODE`,
count(`iblock_element`.`CODE`) AS `cnt`,
GROUP_CONCAT(`iblock_element`.`ID`) AS `IDList`
FR OM `b_iblock_element` `iblock_element`
WH ERE `iblock_element`.`IBLOCK_ID` = 1
GROUP BY `iblock_element`.`CODE`
HAVING count(`iblock_element`.`CODE`) > 1 |
В общем, теперь можно и без прямых SQL-запросов решать нетривиальные задачи с помощью API.