如何在 doctrine 中进行复杂的 SQL 查询
How to make complicated SQL query in doctrine
我有 2 tables:用户 和他们的 积分。
用户有字段:
id
姓名
点有字段:
id
start_date
end_date
count_of_points
user_id
所以有些用户可能有积分也可能没有积分。点数条目受时间间隔限制(从 start_date 到 end_date),并且具有用户在此期间拥有的点数区间.
我需要显示 table 用户此时按总点数排序(时间戳必须在 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
但是这个查询只给我输入了积分 table 的用户,所以我想我必须使用另一个 JOIN 来添加没有积分的用户。这是一个复杂的查询。我不知道如何在原则上实现这一点,因为 DQL 不能使用带 LEFT JOIN 的内部查询。
也许还有其他方法可以解决这个问题?也许我的 tables 模式是错误的,我可以用不同的方式来做吗?
编辑: 忘记了日期条件。更正答案:
在简单的 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);
我有 2 tables:用户 和他们的 积分。
用户有字段:
id
姓名
点有字段:
id
start_date
end_date
count_of_points
user_id
所以有些用户可能有积分也可能没有积分。点数条目受时间间隔限制(从 start_date 到 end_date),并且具有用户在此期间拥有的点数区间.
我需要显示 table 用户此时按总点数排序(时间戳必须在 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
但是这个查询只给我输入了积分 table 的用户,所以我想我必须使用另一个 JOIN 来添加没有积分的用户。这是一个复杂的查询。我不知道如何在原则上实现这一点,因为 DQL 不能使用带 LEFT JOIN 的内部查询。
也许还有其他方法可以解决这个问题?也许我的 tables 模式是错误的,我可以用不同的方式来做吗?
编辑: 忘记了日期条件。更正答案:
在简单的 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);