Сумма из трех Entity
Есть 3 разных модели (для условности пусть называются EOne, ETwo, EThree) и 1 главная модель Organization. В каждой из 3 доп. моделей есть поля paymentSum и organization_id. Нужно сформировать такой запрос в репозитории, чтобы на каждую Organization возвращалась сумма всех трех моделей из сумм paymentSum.
Пример структуры:
Organization
E1
E2
E3
Исходя из этих данных запрос должен вернуть что-то вроде:
Т.е. нужно как-то проссумировать суммы в трех таблицах для каждой Organization. Как это правильно сделать в рамках Symfony?
Для примера вот еще похожий запрос, почти как надо работающий на SQL:
select o.id, o.title, ((select sum(a.payment_sum) from appointment a where a.organization_id = o.id and a.service_at >= '2023-02-01' and a.status IN(1, 6)) + (select sum(ae.payment_sum) from analysis_entry ae where ae.organization_id = o.id and ae.service_at >= '2023-02-01' and ae.status IN(2, 7)) + (select sum(rr.payment_summ) from reanimobile_request rr where rr.organization_id = o.id and rr.resuscitation_at >= '2023-02-01' and rr.status in(2))) totalSum from organization o;
Т.е., как видно для таблиц с агрегацией также используются доп. фильтры (+ нужно будет ограничить пагинацией). Единственное, что, здесь возвращаются организации с пустым totalSum, а их тоже нужно исключить.
Можно ли мой кейс решить полностью или частично на Symfony, в крайнем случае составить какой-то корректный SQL?
Ответы (1 шт):
COALESCE - в данную функцию вы передаете значение paymentSum, если оно = null, функция выберет следующий аргумент, т.е. 0 и далее, через услорвие having выбираем организации, у которых totalSum больше 0.
/**
* @param array $organizations
*
* @return Organization[]
*/
public function getTotalSumByOrganizations(array $organizations): array
{
/**
* result : [
* [
* "organizationId" => 1,
* "organizationTitle" => "Foo",
* "totalSum" => 1234567
* ],
* [
* "organizationId" => 2,
* "organizationTitle" => "Bar",
* "totalSum" => 1234
* ],
* ...
* ]
*
* @var QueryBuilder $qb
*/
$qb = $this->createQueryBuilder('o');
return $qb
->leftJoin('o.EOne', 'eone')
->leftJoin('o.ETwo', 'etwo')
->leftJoin('o.EThree', 'ethree')
->select('o.id')
->select('o.title')
->select('(COALESCE(eone.paymentSum, 0) + COALESCE(etwo.paymentSum, 0) + COALESCE(ethree.paymentSum, 0)) as totalSum')
->andWhere(
$qb
->expr()
->in(
'o.id',
array_map(
static function(Organization $organization) {
return $organization->getId();
},
$organizations
)
)
)
->groupBy('o.id, o.title')
->having('totalSum > 0')
->getQuery()
->getResult();
}




