Reputation: 2333
I have a reseller entity with a 1:n relation to an activity entity.
Each activity performed by the reseller has a value.
What I want to do is to fetch all resellers with the total amount of his activity value and a count of the number of activities for a defined month and for all the year.
I have tried with the query builder:
$qb = $this->getEntityManager()->createQueryBuilder();
$qb
->select(array(
'u.id',
'u.name',
'u.reseller_code',
'u.first_name',
'u.last_name',
'u.email',
'u.country',
'COUNT(am) as numam',
'SUM(ay.activity_value) as sumay',
'SUM(am.activity_value) as sumam'
))
->from('MyBundle:User', 'u')
->leftJoin('u.activities', 'ay', 'WITH', 'ay.activity_year = :year')
->leftJoin('u.activities', 'am', 'WITH', 'am.activity_month = :month AND am.activity_year = :year')
->groupBy('u.id')
->orderBy('u.name', 'ASC')
->setParameter('month', $month)
->setParameter('year', $year)
;
The resulted query is:
SELECT p0_.id AS id0, p0_.name AS name1, p0_.reseller_code AS reseller_code2, p0_.first_name AS first_name3,
p0_.last_name AS last_name4, p0_.email AS email5, p0_.country AS country6, COUNT(a1_.id) AS sclr7,
SUM(a2_.activity_value) AS sclr8, SUM(a1_.activity_value) AS sclr9
FROM reseller p0_
LEFT JOIN activity a2_ ON p0_.id = a2_.reseller_id AND (a2_.activity_year = ?)
LEFT JOIN activity a1_ ON p0_.id = a1_.reseller_id AND (a1_.activity_month = ? AND a1_.activity_year = ?)
GROUP BY p0_.id
ORDER BY p0_.name ASC ([2012,"2",2012])
But the result is not correct, I get numbers like 90 instead of 20 activities and amounts of 900 instead of 90.
Where I am wrong? Thanks for any help!
Upvotes: 0
Views: 2735
Reputation: 151
A bit late in the day, but CASE is currently supported by Doctrine 2; so the IF can be replaced with CASE to achieve the same result if needed.
e.g.
...
'SUM(CASE a.activity_year WHEN :year THEN a.activity_value ELSE 0 END) as sumay',
...
Upvotes: 1
Reputation: 9822
I think this is a SQL problem, not a Doctrine one.
You are using JOIN
two times on the same table, with intersecting conditions. So, you get duplicate records and wrong results for your computation.
I think this might work:
$qb = $this->getEntityManager()->createQueryBuilder(); $qb ->select(array( 'u.id', 'u.name', 'u.reseller_code', 'u.first_name', 'u.last_name', 'u.email', 'u.country', 'COUNT(am) as numam', 'SUM(IF(a.activity_year = :year, a.activity_value, 0)) as sumay', 'SUM(IF(a.activity_year = :year AND a.activity_month = :month, a.activity_value, 0)) as sumam' )) ->from('MyBundle:User', 'u') ->leftJoin('u.activities', 'a') ->groupBy('u.id') ->orderBy('u.name', 'ASC') ->setParameter('month', $month) ->setParameter('year', $year) ;
Basically, the idea is to JOIN just one time, and make your computation in SUM()
.
Edit: By the way, since you said 1:n
relation, JOIN
might be better, instead of LEFT JOIN
Upvotes: 2