Search code examples
mysqlsymfonydoctrine-ormdqldoctrine-query

How to convert this query to doctrine DQL


SELECT apntoken,deviceid,created 
FROM `distribution_mobiletokens` as dm
WHERE userid='20'
and not exists (
    select 1 
    from `distribution_mobiletokens`
    where userid = '20'
    and deviceid = dm.deviceid
    and created > dm.created
    )

What this query does is selects all mobiletokens where the user id is equal to 20 and the deviceid is the same but chooses the newest apntoken for the device.

My database looks like below.

enter image description here

For more information on this query, I got this answer from another question I asked here(How to group by in SQL by largest date (Order By a Group By))

Things I've Tried

$mobiletokens = $em->createQueryBuilder()
          ->select('u.id,company.id as companyid,user.id as userid,u.apntoken')
          ->from('AppBundle:MobileTokens', 'u')
          ->leftJoin('u.companyId', 'company')
          ->leftJoin('u.userId', 'user')
          ->where('u.status = 1 and user.id = :userid')
          ->setParameter('userid',(int)$jsondata['userid'])
          ->groupby('u.apntoken')
          ->getQuery()
          ->getResult();

       //@JA - Get the list of all the apn tokens we need to send the message to.
       foreach($mobiletokens as $tokenobject){
           $deviceTokens[] = $tokenobject["apntoken"];
           echo $tokenobject["apntoken"]."\n";
       }

        die();

This gives me the incorrect response of

63416A61F2FD47CC7B579CAEACB002CB00FACC3786A8991F329BB41B1208C4BA
9B25BBCC3F3D2232934D86A7BC72967A5546B250281FB750FFE645C8EB105AF6
latestone

Any help here is appreciated!

Other Information

Data with SELECT * FROM

enter image description here

Data after using the SQL I provided up top.

enter image description here


Solution

  • You could use a subselect created with the querybuilder as example:

    public function selectNewAppToken($userId)
    {
        // get an ExpressionBuilder instance, so that you
        $expr = $this->_em->getExpressionBuilder();
    
        // create a subquery in order to take all address records for a specified user id
        $sub = $this->_em->createQueryBuilder()
            ->select('a')
            ->from('AppBundle:MobileTokens', 'a')
            ->where('a.user = dm.id')
            ->andWhere('a.deviceid = dm.deviceid')
            ->andWhere($expr->gte('a.created','dm.created'));
    
    
        $qb = $this->_em->createQueryBuilder()
            ->select('dm')
            ->from('AppBundle:MobileTokens', 'dm')
            ->where($expr->not($expr->exists($sub->getDQL())))
            ->andWhere('dm.user = :user_id')
            ->setParameter('user_id', $userId);
    
        return $qb->getQuery()->getResult();
    }