Join 带连接的条令查询生成器嵌套orX和andX条件

Join 带连接的条令查询生成器嵌套orX和andX条件,join,doctrine,repository,conditional-statements,query-builder,Join,Doctrine,Repository,Conditional Statements,Query Builder,我有两个实体User和CalendarEvent。“我的用户”附加到工厂,calendarEvent可用于了解用户是否“借用”到他所属工厂的其他工厂 我的两个实体如下所示: 用户: class User extends BaseUser { /** * @ORM\Id * @ORM\Column(type="integer") * @ORM\GeneratedValue(strategy="AUTO") */ protected $id;

我有两个实体
User
CalendarEvent
。“我的用户”附加到工厂,calendarEvent可用于了解用户是否“借用”到他所属工厂的其他工厂

我的两个实体如下所示:

用户:

class User extends BaseUser
{

    /**
     * @ORM\Id
     * @ORM\Column(type="integer")
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    /**
     * @var string
     * @ORM\Column(name="firstname", type="string", length=255, nullable=true)
     */
    private $firstname;

    /**
     * @var string
     * @ORM\Column(name="lastname", type="string", length=255, nullable=true)
     */
    private $lastname;

    /**
     * @ORM\OneToMany(targetEntity="AppBundle\Entity\CalendarEvent", mappedBy="user")
     */
    private $events;

    /**
     * @ORM\ManyToOne(targetEntity="AppBundle\Entity\Factory", inversedBy="users")
     * @ORM\JoinColumn(name="factory_id", referencedColumnName="id")
     */
    private $factory;

}
日历事件:

class CalendarEvent
{

    /**
     * @var int
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id; 

    /**
     * @var \DateTime
     * @ORM\Column(type="datetime", name="event_start")
     */
    private $startDate;

    /**
     * @var \DateTime
     * @ORM\Column(type="datetime", name="event_end")
     */
    private $endDate;

    /**
     * @var bool
     * @ORM\Column(name="isLoan", type="boolean")
     */
    private $isLoan = TRUE;

    /**
     * @ORM\ManyToOne(targetEntity="Factory")
     * @ORM\JoinColumn(name="factory_id", referencedColumnName="id", nullable = true)
     */
    private $factory;

    /**
     * @ORM\ManyToOne(targetEntity="UserBundle\Entity\User", inversedBy="events")
     * @ORM\JoinColumn(name="user_id", referencedColumnName="id")
     */
    private $user;
}
我想做的是在
UserRepository
中创建一个repository函数,当我用factory in entry参数触发请求时,它会让我知道实际是工厂的人

为了实现这一点,我尝试指定一个条件。这种情况应该是这样的:

select * from user where (
    (user.factory == $idfactory AND not loaned_to_other_factory) OR 
    (user.factory != $idfactory AND loaned_to_my_factory)
)
要知道用户是否已被租借到我的工厂,必须验证以下条件:

Does a record exist in CalendarEvent where startDate < NOW and endDate > NOW and loaned == true and factory == $factory

我真的希望我说的有道理,有人能给我一些实现这一点的建议。提前感谢

我想您可以将现有查询转换为not in

$notLoanedToOther = $this->createQueryBuilder("e")
                         ->select("e.user")
                         ->from("CalendarEvent","e")
                         ->andWhere('e.startDate < :now')
                         ->andWhere('e.endDate > :now')
                         ->getDQL();

$loanedToMyFactory = $this->createQueryBuilder("e")
                          ->select("e.user")
                          ->from("CalendarEvent","e")
                          ->where('e.factory = :idf')
                          ->andWhere('e.startDate < :now')
                          ->andWhere('e.endDate > :now')
                          ->getDQL();

$qb = $this->_em->createQueryBuilder();
 $qb->select('u')
    ->from($this->_entityName, 'u')
    ->where(
        $qb->expr()->not(
            $qb->expr()->in(
            'u.id',
            $notLoanedToOther
            )
        )
    )
    ->andWhere(
        $qb->expr()->in(
        'u.id',
        $loanedToMyFactory
        )   
    )
    ->where(
        $qb->expr()->orX(
                $qb->expr()->andX(
                    $qb->expr()->eq('u.factory', ':idf'),
                    $qb->expr()->not(
                        $qb->expr()->in(
                        'u.id',
                        $notLoanedToOther
                        )
                    )
                ), 
                $qb->expr()->andX(
                    $qb->expr()->neq('u.factory', ':idf'),
                    $qb->expr()->in(
                    'u.id',
                    $loanedToMyFactory
                    )
                )
            )
        )
    ->setParameter('idf', $idFactory)
    ->setParameter('now', $someDate)
    ;
$notloadetoother=$this->createQueryBuilder(“e”)
->选择(“电子用户”)
->来自(“日历事件”、“e”)
->andWhere('e.startDate<:now')
->andWhere('e.endDate>:now')
->getDQL();
$loanedToMyFactory=$this->createQueryBuilder(“e”)
->选择(“电子用户”)
->来自(“日历事件”、“e”)
->其中('e.factory=:idf')
->andWhere('e.startDate<:now')
->andWhere('e.endDate>:now')
->getDQL();
$qb=$this->_em->createQueryBuilder();
$qb->选择('u')
->from($this->\u entityName,'u')
->在哪里(
$qb->expr()->非(
$qb->expr()->in(
“u.id”,
$notloanedother
)
)
)
->在哪里(
$qb->expr()->in(
“u.id”,
$loanedToMyFactory
)   
)
->在哪里(
$qb->expr()->orX(
$qb->expr()->andX(
$qb->expr()->eq('u.factory',':idf'),
$qb->expr()->非(
$qb->expr()->in(
“u.id”,
$notloanedother
)
)
), 
$qb->expr()->andX(
$qb->expr()->neq('u.factory',':idf'),
$qb->expr()->in(
“u.id”,
$loanedToMyFactory
)
)
)
)
->setParameter('idf',$idFactory)
->setParameter('now',$someDate)
;

根据您在SQL中指定的条件,使用带有联接的简单DQL查询,而不是复杂的not in子句,怎么样

从用户位置选择*( (user.factory==$idfactory且未贷给其他工厂)或 (user.factory!=$idfactory并借给我的工厂) )

您可以用DQL编写它的等价物,如下所示

SELECT u
FROM User u
LEFT JOIN u.events nl WITH e.startDate < :now AND e.endDate > :now
LEFT JOIN u.events l WITH e.startDate < :now AND e.endDate > :now AND e.factory = :idf
WHERE (
    u.factory = :idf AND nl.id IS NULL
) OR (
    u.factory != :idf AND l.id IS NOT NULL
)
选择u
来自用户u
左键使用e.startDate<:now和e.endDate>立即加入u.events nl
左键使用e.startDate<:now和e.endDate>:now和e.factory=:idf连接u.events l
在哪里(
u、 factory=:idf和nl.id为NULL
)或(
u、 工厂!=:idf和l.id不为空
)
使用附加子句将事件实体与用户连接两次,一个用于loaned,另一个用于not loaded,然后应用您的条件,我添加了
IS NULL
IS not NULL
过滤器以满足您的exists和not exists条件

SELECT u
FROM User u
LEFT JOIN u.events nl WITH e.startDate < :now AND e.endDate > :now
LEFT JOIN u.events l WITH e.startDate < :now AND e.endDate > :now AND e.factory = :idf
WHERE (
    u.factory = :idf AND nl.id IS NULL
) OR (
    u.factory != :idf AND l.id IS NOT NULL
)