如何在排除特定日期元素的 OneToMany 关系中进行 DQL 查询?
How to make a DQL query in a OneToMany relation that exclude elements at a certain date?
我在 Symfony 中遇到查询问题。我有两个具有 OneToMany 关系的实体:
/**
* Field
*
* @ORM\Table(name="field")
* @ORM\Entity(repositoryClass="MyBundle\Repository\FieldRepository")
*/
class Field
{
.
.
.
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="Booking", mappedBy="field", cascade={"remove","persist"})
*/
private $bookings;
并且:
/**
* Booking
*
* @ORM\Table(name="booking")
* @ORM\Entity(repositoryClass="MyBundle\Repository\BookingRepository")
*/
class Booking
{
.
.
.
/**
* @var \DateTime
*
* @ORM\Column(name="date", type="datetime", nullable = true)
*/
private $date;
/**
* @ORM\ManyToOne(targetEntity="Field", inversedBy="bookings")
* @ORM\JoinColumn(name="field_id", referencedColumnName="id")
*/
private $field;
而且我想获得在特定日期免费(未 预订)的字段。我试过这个:
public function findFreeFields($date){
$em = $this->getEntityManager();
$queryText = "SELECT f, FROM MyBundle:Field f JOIN f.bookings b ";
$queryText .= "WHERE b.date!=:date";
$query = $em->createQuery($queryText);
$query->setParameter('date', $date);
return $query->getResult();
问题是,例如,如果我有一个名为 "field1" 的字段,其中有 4 个预订,其中一个预订的日期是 2017 年 5 月 20 日。我用 findFreeFields()
查找那个日期 (20/05/2017) 的所有空闲字段,但我得到一个 "field1" 重复了三次的列表,这显然是错误的。 "field1" 不能出现在结果列表中,因为它是在指定日期预订的。
使用 DISTINCT 我没有得到重复的结果,但仍然得到 "field1" 结果。
public function findFreeFields($date){
$em = $this->getEntityManager();
$queryText = "SELECT DISTINCT f, FROM MyBundle:Field f JOIN f.bookings b ";
$queryText .= "WHERE b.date!=:date";
$query = $em->createQuery($queryText);
$query->setParameter('date', $date);
return $query->getResult();
那么,我必须如何编写 DQL 查询才能排除在特定日期有预订的字段?
解决方案是做一个子查询,选择所有在指定日期预订的文件,然后使用该子查询过滤掉所有字段的选择。
为了清楚起见,我使用了 QueryBuilder 并划分了子查询和查询,但您可以根据自己的喜好随意修改任何内容。
...
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$bookedFieldsQuery = $qb->select('bookedf')
->from('MyBundle:Field', 'bookedf')
->join('bookedf.bookings', 'b', 'WITH' ,'b.date = :date')
->getDQL();
$qb = $em->createQueryBuilder();
$availableFieldsQuery = $qb->select('f')
->from('MyBundle:Field', 'f')
->where($qb->expr()->notIn('f', $bookedFieldsQuery))
->getQuery();
$availableFields->setParameter('date', $date);
return $availableFieldsQuery->getResult();
...
最终的 DQL 本身:
SELECT f FROM MyBundle:Field f WHERE f.id NOT IN(SELECT bookedf.id FROM MyBundle:Field bookedf INNER JOIN bookedf.bookings b WITH b.date = :date)
我在 Symfony 中遇到查询问题。我有两个具有 OneToMany 关系的实体:
/**
* Field
*
* @ORM\Table(name="field")
* @ORM\Entity(repositoryClass="MyBundle\Repository\FieldRepository")
*/
class Field
{
.
.
.
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255)
*/
private $name;
/**
* @ORM\OneToMany(targetEntity="Booking", mappedBy="field", cascade={"remove","persist"})
*/
private $bookings;
并且:
/**
* Booking
*
* @ORM\Table(name="booking")
* @ORM\Entity(repositoryClass="MyBundle\Repository\BookingRepository")
*/
class Booking
{
.
.
.
/**
* @var \DateTime
*
* @ORM\Column(name="date", type="datetime", nullable = true)
*/
private $date;
/**
* @ORM\ManyToOne(targetEntity="Field", inversedBy="bookings")
* @ORM\JoinColumn(name="field_id", referencedColumnName="id")
*/
private $field;
而且我想获得在特定日期免费(未 预订)的字段。我试过这个:
public function findFreeFields($date){
$em = $this->getEntityManager();
$queryText = "SELECT f, FROM MyBundle:Field f JOIN f.bookings b ";
$queryText .= "WHERE b.date!=:date";
$query = $em->createQuery($queryText);
$query->setParameter('date', $date);
return $query->getResult();
问题是,例如,如果我有一个名为 "field1" 的字段,其中有 4 个预订,其中一个预订的日期是 2017 年 5 月 20 日。我用 findFreeFields()
查找那个日期 (20/05/2017) 的所有空闲字段,但我得到一个 "field1" 重复了三次的列表,这显然是错误的。 "field1" 不能出现在结果列表中,因为它是在指定日期预订的。
使用 DISTINCT 我没有得到重复的结果,但仍然得到 "field1" 结果。
public function findFreeFields($date){
$em = $this->getEntityManager();
$queryText = "SELECT DISTINCT f, FROM MyBundle:Field f JOIN f.bookings b ";
$queryText .= "WHERE b.date!=:date";
$query = $em->createQuery($queryText);
$query->setParameter('date', $date);
return $query->getResult();
那么,我必须如何编写 DQL 查询才能排除在特定日期有预订的字段?
解决方案是做一个子查询,选择所有在指定日期预订的文件,然后使用该子查询过滤掉所有字段的选择。
为了清楚起见,我使用了 QueryBuilder 并划分了子查询和查询,但您可以根据自己的喜好随意修改任何内容。
...
$em = $this->getDoctrine()->getManager();
$qb = $em->createQueryBuilder();
$bookedFieldsQuery = $qb->select('bookedf')
->from('MyBundle:Field', 'bookedf')
->join('bookedf.bookings', 'b', 'WITH' ,'b.date = :date')
->getDQL();
$qb = $em->createQueryBuilder();
$availableFieldsQuery = $qb->select('f')
->from('MyBundle:Field', 'f')
->where($qb->expr()->notIn('f', $bookedFieldsQuery))
->getQuery();
$availableFields->setParameter('date', $date);
return $availableFieldsQuery->getResult();
...
最终的 DQL 本身:
SELECT f FROM MyBundle:Field f WHERE f.id NOT IN(SELECT bookedf.id FROM MyBundle:Field bookedf INNER JOIN bookedf.bookings b WITH b.date = :date)