Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

doctrine dql where clause interpretation with associated entity

Given this entity

class SystemRecord
{
    /**
     * @ORM\Id
     * @ORM\Column(type="integer", name="ID")
     * @ORM\GeneratedValue
     * @var int
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="Application\Entity\User")
     * @ORM\JoinColumn(name="USER_SERIAL", referencedColumnName="SERIAL", nullable=false)
     * @var User
     */
    private $user;

    /**
     * @ORM\Column(type="utcdatetime", name="DATE_DATA_WAS_FETCHED", nullable=false)
     * @var DateTimeInterface
     */
    private $dateDataWasFetched;
}

...and this dql

$dql = "
    select r
      from Application\\Entity\\SystemRecord r
      join Application\\Entity\\User u
     where r.dateDataWasFetched = (
         select max(r2.dateDataWasFetched)
           from Application\\Entity\\SystemRecord r2
     )
       and u.serial = :serial
";

$query = $this->getEntityManager()->createQuery($dql);
$query->setParameter('serial', $user->getSerial());
$sql = $query->getSql();

... I'm hoping to get "the SystemRecords for the user with the specified serial, but only those with the most recent date out of any SystemRecord". In other words, procedurally, "find the most recent date of any SystemRecord for any user. Then find records for the specified user which occurred on that date."

If I were writing sql, I would write

select *
  from SYSTEM_RECORDS r
  join USER u
    on r.USER_SERIAL = u.SERIAL
 where DATE_DATA_WAS_FETCHED = (select max(DATE_DATA_WAS_FETCHED) from SYSTEM_RECORDS)
   and u.SERIAL = ?

But, doctrine is giving me the following sql

SELECT ...fields from s0_ ...
  FROM SYSTEM_RECORDS s0_ 
 INNER 
  JOIN 
  USER u1_
   ON (s0_.DATE_DATA_WAS_FETCHED = (SELECT max(s2_.DATE_DATA_WAS_FETCHED) AS dctrn__1
                                     FROM SYSTEM_RECORDS s2_) AND u1_.SERIAL = ?)

Which isn't what I want. That gives me "SystemRecords for all users whose SystemRecords have the same date as the most recent SystemRecords for the user with the specified serial".

How do I formulate my query using dql?


like image 788
goat Avatar asked May 04 '15 19:05

goat


1 Answers

If I understand you correctly you need to use a sub query like you did but I think you are missing the in expression. With QueryBuilder you would built the query to get your result like this (I always write my queries with QueryBuilder):

$qb->select(r)
   ->from('SystemRecord', 'r')
   ->join('r.user', 'u')
   ->where(
       $qb->expr()->in(
           'r.dateDataWasFetched',
           "SELECT max(r2.dateDataWasFetched) FROM Application\\Entity\\SystemRecord r2"
       )
   )
   ->andWhere('u.serial' = :user_serial)
   ->setParameter('user_serial', $user->getSerial())
   ->getQuery()
   ->getResult();

This answer is based on this answer to similar question on stackoverflow.

EDIT:

If you really want the DQL then you can easily get it from your QueryBuilder instance after building the query using the getDQL method like this:

$dql = $qb->getQuery()->getDQL();
like image 104
Wilt Avatar answered Oct 31 '22 20:10

Wilt