symfony(doctrine):DQL查询,如何排除结果?

时间:2016-04-15 02:18:57

标签: sql symfony doctrine dql

我对SQL有非常基本的了解,不知道如何修改我的查询,因此它会返回预期的结果。

我的实体Activity有一个字段成员(manyToMany关系)。一项活动可以由几个成员完成。 我想选择特定成员参与的所有活动。我知道会员的身份证(我的变量$selfId)。

以下是我在 ActivityRepository 中所做的事情:

public function getCollectiveActivities($selfId)
{
    $qb = $this->createQueryBuilder('a');
    $qb->join('a.members', 'm')
       ->where('m.id != :selfId')
       ->setParameter('selfId', $selfId);

    return $qb
        ->getQuery()
        ->getResult();
}

我的问题:当一个活动“拥有”两个或更多成员时,如果其中一个成员将$ selfId作为id,则此活动最终会出现在我的查询结果中。 但由于此活动的其中一个成员的ID为$ selfId,因此不应返回。我做错了什么?

修改

我认为我需要更加严格,我只是不知道如何。 假设我有两个活动:

activity1 which is owned by member1 and member2
activity2 which is owned by member3 and member4

$ selfId = 3(这意味着我不想获取member3拥有的活动)

据我所知,join子句可能会返回如下行:

activity1 | memberId: 1 (different from selfId = 3 so activity1 will be fetched)
activity1 | memberId: 2 (different from selfId = 3 so activity1 will be fetched)
activity2 | memberId: 3 (= selfId so activity2 shouldn't be fetched)
activity2 | memberId: 4 (different from selfId = 3 so activity2 WILL be fetched. PROBLEM???)

编辑2

其他人已经遇到了同样的问题,发现了this solutionthis one,但他们看起来有些笨拙。关于如何改进它们的任何线索都是受欢迎的。

3 个答案:

答案 0 :(得分:1)

您必须专门选择想要保湿的结果。你看到的问题是你只是选择活动。

然后,当您调用$ activity-> getMembers()时,会员会延迟加载,但这不会考虑您的查询。

你可以这样避免:

public function getCollectiveActivities($selfId)
{
    $qb = $this->createQueryBuilder('a');
    $qb->addSelect('m');
    $qb->join('a.members', 'm')
       ->where('m.id != :selfId')
       ->setParameter('selfId', $selfId);

    return $qb
        ->getQuery()
        ->getResult();
}

这意味着您获取的活动已经使其成员保持水分并受查询条件的限制。

答案 1 :(得分:0)

public function getCollectiveActivities($selfId)
{

    return $this->createQueryBuilder('a')
        ->join('a.members', 'm')
        ->where($qb->expr()->neq('c.selfId', $selfId))     
        ->getQuery()
        ->getResult();

}

答案 2 :(得分:0)

我最终调整了@NtskX发布的a solution

public function getCollectiveActivities($selfId)
{
    $qbMyCollectives = $this->createQueryBuilder('ca');
    $qbMyCollectives
        ->select('ca.id')
        ->leftJoin('ca.members', 'm')
        ->where('m.id = :selfId')
        ->setParameter('selfId', $selfId);

    $qb = $this->createQueryBuilder('a');
    $qb
        ->where($qb->expr()->notIn('a.id', $qbMyCollectives->getDQL()))
        ->setParameter('selfId', $selfId); // I had to declare the parameter one more time

    return $qb
        ->getQuery()
        ->getResult();
}

我真的以为有人会出现更好的方式来加入,所以其他任何答案都非常受欢迎。