QueryBuilder/Doctrine Select 加入groupby
QueryBuilder/Doctrine Select join groupby
所以最近我一直在思考这个问题,但由于我缺乏 doctrine2 和 symfony 查询生成器的开发,所以还没有找到解决方案。
我有 2 个 table:
目标:id,user_id,target_value...
储蓄:id,goal_id,金额
我需要根据目标计算 select(我 table 中的所有信息都来自目标 table,除了我需要计算 SUM(amount)从每个目标的节省 table 中,所以我可以向用户显示他为他的目标节省了多少钱)
这是 MySQL 查询:
select
admin_goals.created,
admin_goals.description,
admin_goals.goal_date,
admin_goals.value,
admin_goals.budget_categ,
sum(admin_savings.value)
from admin_goals
inner join admin_savings on admin_savings.goal_id=admin_goals.id
where admin_goals.user_id=1
group by admin_goals.id
它 returns 是我想要的,但我不知道如何使用学说或查询构建器来实现它,你能给我举个这两种方式的例子吗?
我非常感激!
如果你使用 createQuery(),那么你可以这样做:
$dqlStr = <<<"DSQL"
select
admin_goals.created,
admin_goals.description,
admin_goals.goal_date,
admin_goals.value,
admin_goals.budget_categ,
sum(admin_savings.value)
from admin_goals
inner join admin_savings on admin_savings.goal_id=admin_goals.id
where admin_goals.user_id=1
group by admin_goals.id
DSQL;
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery($dqlStr);
$query->getResult();
另一方面,如果您想使用 createQueryBuilder(),您可以检查这个 link:http://inchoo.net/dev-talk/symfony2-dbal-querybuilder/
我假设您只需要这些字段,而不是您的 AdminGoals
实体。在你的 AdminGoalsRepository
上你可以做这样的事情:
public function getGoalsByUser(User $user)
{
$qb = $this->createQueryBuilder('goal');
$qb->select('SUM(savings.value) AS savings_value')
->addSelect('goal.created')
->addSelect('goal.description')
->addSelect('goal.goalDate')
->addSelect('goal.value')
->addSelect('goal.budgetCat') //is this an entity? it will be just an ID
->join('goal.adminSavings', 'savings', Join::WITH))
->where($qb->expr()->eq('goal.user', ':user'))
->groupBy('goal.id')
->setParameter('user', $user);
return $qb->getQuery()->getScalarResult();
}
请记住,return 对象将是一个行数组,每一行都是一个关联的数组,其键与上面的映射类似。
编辑
更新问题后,我将更改我建议的函数,但如果其他人希望看到差异,我将保留上面的示例。
首先,由于这是 AdminSavings
和 AdminGoals
之间的单向 ManyToOne,自定义查询应该在 AdminSavingsRepository
中(与上面不同).此外,由于您想要一个 aggregated field,这将 "break" 您的一些数据获取。当您不只是渲染模板时,尽量保持尽可能多的 OOP。
public function getSavingsByUser(User $user)
{
$qb = $this->createQueryBuilder('savings');
//now we can use the expr() function
$qb->select('SUM(savings.value) AS savings_value')
->addSelect('goal.created')
->addSelect('goal.description')
->addSelect('goal.goalDate')
->addSelect('goal.value')
->addSelect('goal.budgetCat') //this will be just an ID
->join('savings.goal', 'goal', Join::WITH))
->where($qb->expr()->eq('goal.user', ':user'))
->groupBy('goal.id')
->setParameter('user', $user);
return $qb->getQuery()->getScalarResult();
}
奖金
public function FooAction($args)
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
//check if user is User etc depends on your config
...
$savings = $em->getRepository('AcmeBundle:AdminSavings')->getSavingsByUser($user);
foreach($savings as $row) {
$savings = $row['savings_value'];
$goalId = $row['id'];
$goalCreated = $row['created'];
[...]
}
[...]
}
所以最近我一直在思考这个问题,但由于我缺乏 doctrine2 和 symfony 查询生成器的开发,所以还没有找到解决方案。
我有 2 个 table: 目标:id,user_id,target_value... 储蓄:id,goal_id,金额
我需要根据目标计算 select(我 table 中的所有信息都来自目标 table,除了我需要计算 SUM(amount)从每个目标的节省 table 中,所以我可以向用户显示他为他的目标节省了多少钱)
这是 MySQL 查询:
select
admin_goals.created,
admin_goals.description,
admin_goals.goal_date,
admin_goals.value,
admin_goals.budget_categ,
sum(admin_savings.value)
from admin_goals
inner join admin_savings on admin_savings.goal_id=admin_goals.id
where admin_goals.user_id=1
group by admin_goals.id
它 returns 是我想要的,但我不知道如何使用学说或查询构建器来实现它,你能给我举个这两种方式的例子吗?
如果你使用 createQuery(),那么你可以这样做:
$dqlStr = <<<"DSQL"
select
admin_goals.created,
admin_goals.description,
admin_goals.goal_date,
admin_goals.value,
admin_goals.budget_categ,
sum(admin_savings.value)
from admin_goals
inner join admin_savings on admin_savings.goal_id=admin_goals.id
where admin_goals.user_id=1
group by admin_goals.id
DSQL;
$em = $this->getDoctrine()->getManager();
$query = $em->createQuery($dqlStr);
$query->getResult();
另一方面,如果您想使用 createQueryBuilder(),您可以检查这个 link:http://inchoo.net/dev-talk/symfony2-dbal-querybuilder/
我假设您只需要这些字段,而不是您的 AdminGoals
实体。在你的 AdminGoalsRepository
上你可以做这样的事情:
public function getGoalsByUser(User $user)
{
$qb = $this->createQueryBuilder('goal');
$qb->select('SUM(savings.value) AS savings_value')
->addSelect('goal.created')
->addSelect('goal.description')
->addSelect('goal.goalDate')
->addSelect('goal.value')
->addSelect('goal.budgetCat') //is this an entity? it will be just an ID
->join('goal.adminSavings', 'savings', Join::WITH))
->where($qb->expr()->eq('goal.user', ':user'))
->groupBy('goal.id')
->setParameter('user', $user);
return $qb->getQuery()->getScalarResult();
}
请记住,return 对象将是一个行数组,每一行都是一个关联的数组,其键与上面的映射类似。
编辑
更新问题后,我将更改我建议的函数,但如果其他人希望看到差异,我将保留上面的示例。
首先,由于这是 AdminSavings
和 AdminGoals
之间的单向 ManyToOne,自定义查询应该在 AdminSavingsRepository
中(与上面不同).此外,由于您想要一个 aggregated field,这将 "break" 您的一些数据获取。当您不只是渲染模板时,尽量保持尽可能多的 OOP。
public function getSavingsByUser(User $user)
{
$qb = $this->createQueryBuilder('savings');
//now we can use the expr() function
$qb->select('SUM(savings.value) AS savings_value')
->addSelect('goal.created')
->addSelect('goal.description')
->addSelect('goal.goalDate')
->addSelect('goal.value')
->addSelect('goal.budgetCat') //this will be just an ID
->join('savings.goal', 'goal', Join::WITH))
->where($qb->expr()->eq('goal.user', ':user'))
->groupBy('goal.id')
->setParameter('user', $user);
return $qb->getQuery()->getScalarResult();
}
奖金
public function FooAction($args)
{
$em = $this->getDoctrine()->getManager();
$user = $this->getUser();
//check if user is User etc depends on your config
...
$savings = $em->getRepository('AcmeBundle:AdminSavings')->getSavingsByUser($user);
foreach($savings as $row) {
$savings = $row['savings_value'];
$goalId = $row['id'];
$goalCreated = $row['created'];
[...]
}
[...]
}