Doctrine:使用1(n)与count()和sum()的关联获取

时间:2012-03-07 18:01:11

标签: mysql doctrine symfony doctrine-orm

我有一个与活动实体有1:n关系的经销商实体。

经销商执行的每项活动都有一个值。

我想要做的是获取所有经销商的活动总金额以及定义的月份和全年的活动数量。

我尝试过使用查询构建器:

$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)
;

结果查询是:

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])

但结果不正确,我得到的数字是90而不是20个活动,数量为900而不是90.

我哪里错了?谢谢你的帮助!

2 个答案:

答案 0 :(得分:2)

我认为这是一个SQL问题,而不是一个学说问题。 您在同一个表上使用JOIN两次,并且具有相交条件。因此,您的计算会得到重复的记录和错误的结果。

我认为这可行:

$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)
;

基本上,想法只是加入一次,并在SUM()进行计算。

编辑:顺便说一下,既然您说过1:n关系,JOIN可能会更好,而不是LEFT JOIN

答案 1 :(得分:1)

当天晚些时候,但CASE目前得到了Doctrine 2的支持;所以IF可以用CASE替换,以便在需要时获得相同的结果。

e.g。

...

'SUM(CASE a.activity_year WHEN :year THEN a.activity_value ELSE 0 END) as sumay',

...