QueryBuilder/Doctrine Select join groupby

3
最近我一直在思考一个问题,但由于我对Doctrine2和Symfony查询构建器的开发经验有限,还未找到解决方案。
我有两个表: Goals:id,user_id,target_value…… Savings:id,goal_id,amount
我需要从Goals表中进行选择(我的所有信息都来自Goals表),除此之外,我还需要在每个目标上对Savings表中的amount字段求和,这样可以向用户展示他为目标存了多少钱。
以下是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

这段代码返回了我需要的结果,但是我不知道如何用Doctrine或者查询构建器实现它,请你能否给我展示一下这两种方式的例子呢? enter image description here 非常感谢! enter image description here


你必须正确定义你的实体。你可以参考这个链接:http://stackoverflow.com/questions/18939112/symfony2-doctrine-custom-repository-class-semantical-error-line-0-col-14-near - Sharif Mamun
2个回答

2
我假设你只需要这些字段而不是你的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();
}

请记住,返回的对象将是一行行数组,每行都是一个关联数组,其中包含像上面映射的键。
编辑
在更新问题后,我将更改我的建议函数,但将保留上面的示例供其他人查看差异。
首先,由于这是AdminSavings和AdminGoals之间的单向ManyToOne关系,因此自定义查询应该在AdminSavingsRepository中(而不是像上面那样)。此外,由于您想要一个{{link1:聚合字段}},这将“破坏”一些数据获取。在您不仅仅呈现模板时,请尽量保持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'];
        [...]
    }
    [...]
}

我得到了一个错误:在类“AppBundle\Entity\Goal”上尝试调用方法“createQueryBuilder”。控制器:$ x = $goal->getGoalsByUser($user); // $goal = new Goal(); ... 我把你的函数放在了Goal Entity中,我做错了什么吗? - doglover1337
正如我所说,这必须在你的 AppBundle\Entity\GoalRepository 上完成。如果你没有一个,你可以生成它。 - stevenll
谢谢您的回答,我终于生成了我的存储库并运行了函数。我得到了一个错误:[语义错误]第0行,第173列附近的“savings WHERE”:错误:类AppBundle\Entity\Goal没有名为adminSavings的关联。这基本上意味着我在表中没有adminsavings(这是总和)字段,但我不想更改我的目标表结构,如果我想显示来自其他表的3-4个sum(),我需要为每个sum()创建一个表列吗? - doglover1337
我需要在这一行写什么? ->join('goal.adminSavings', 'savings', Join::WITH)) ?? 我的goal表中没有admin_savings字段..但是在savings表中有goal_id字段..所以很多储蓄都与一个目标相关联。 - doglover1337
你能否更新你的问题并提供实体映射吗?至少要包含你正在尝试获取的部分。 - stevenll
显示剩余2条评论

0
如果您使用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(),你可以查看这个链接:http://inchoo.net/dev-talk/symfony2-dbal-querybuilder/


我也尝试了你的解决方案,但它不起作用,我一开始得到一个语法错误,没有引号?或者是不需要它们?如果我加上引号,我会得到以下信息:尝试在类“Doctrine\DBAL\Connection”上调用方法“createQuery”。您是要调用“createQueryBuilder”吗?...我只想运行一个简单的查询,天哪.. - doglover1337
我本意不是要调用 createQueryBuilder()。对于复杂的查询,使用 QueryBuilder 可能会导致混乱并浪费时间。我添加了 '$em = $this->getDoctrine()->getManager();' 并进行了更新! - Sharif Mamun
好的,我已经让它运行起来了,但是出现了这个错误:[语义错误]第0行,第151列附近的'admin_goals inner':错误:类'admin_goals'未定义。..看起来错误出现在admin_goals内部连接的部分。 - doglover1337
这意味着您的原始SQL查询存在问题! - Sharif Mamun
我曾经在mysql(phpmyadmin)中复制粘贴相同的查询并成功运行,但在页面上却出现了错误。 - doglover1337
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接