如何在学说

时间:2016-05-25 08:58:25

标签: mysql symfony doctrine-orm doctrine-query

我有2个表:用户和他们的

用户有字段:

  • ID

  • 名称

积分有字段:

  • ID

  • 起始日期

  • END_DATE

  • count_of_points

  • USER_ID

所以有些用户可能有或没有积分。点条目受时间间隔(从 start_date end_date )的限制,并且具有用户在此间隔内拥有的点数。

我需要在此时按总点数排序的用户显示表(时间戳必须在 start_date end_date 之间)并在视图中稍后显示此总和值。如果用户没有积分,则此计数必须等于0.

我有这样的事情:

$qb = $this->getEntityManager()
        ->getRepository('MyBundle:User')
        ->createQueryBuilder('u');
    $qb->select('u, SUM(p.count_of_points) AS HIDDEN sum_points')
        ->leftJoin('u.points', 'p')
        ->orderBy('sum_points', 'DESC'); 
$qb->groupBy('u');
        return $qb->getQuery()
            ->getResult();

但是这对日期间隔没有限制,并且没有我可以在对象视图中使用的和点字段。

我试图找到如何解决这个问题,我在SQL中做了类似的事情:

SELECT u.*, up.points FROM users AS u LEFT OUTER JOIN
      (SELECT u.*, SUM(p.count_of_points) AS points FROM `users` AS u
      LEFT OUTER JOIN points AS p ON p.user_id = u.id
      WHERE p.start_date <= 1463578691 AND p.end_date >= 1463578691
      ) AS up ON u.id = up.id ORDER BY up.points DESC

但是这个查询只给了我用户在点表中的条目,所以我想我必须使用另一个JOIN来添加没有点的用户。这是一个复杂的查询。我不知道如何在doctrine中实现它,因为DQL不能使用LEFT JOIN的内部查询。

也许有其他方法可以解决这个问题?也许我的表架构是错误的,我可以这样做吗?

1 个答案:

答案 0 :(得分:1)

编辑:忘记了日期条件。更正回答:

在普通的MySQL中,您的查询将如下所示:

SELECT u.id, u.name, COALESCE(SUM(p.count_of_points),0) AS sum_points 
FROM Users u 
LEFT JOIN Points p ON p.user_id=u.id 
WHERE (p.start_date <= 1463578691 AND p.end_date >= 1463578691) OR p.id IS NULL
GROUP BY u.id
ORDER BY sum_points DESC

COALESCE函数发送回第一个非NULL参数,因此如果用户没有点,则总和将导致NULL,但COALESCE将返回0.

我不确定使用Doctrine查询构建器进行翻译,但您可以尝试:

$qb = $this->getEntityManager()->createQueryBuilder();

$qb->select('u')
   ->addSelect('COALESCE(SUM(p.count_of_points),0) AS sum_points')
   ->from('User', 'u')
   ->leftjoin('u.points', 'p')
   ->where('(p.start_date <= ?1 AND p.end_date >= ?1) OR p.id IS NULL')
   ->groupBy('u.id')
   ->orderBy('sum_points','DESC')
   ->setParameter(1, $date_now);