简体   繁体   中英

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.

在此处输入图片说明

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

在此处输入图片说明

Data after using the SQL I provided up top.

在此处输入图片说明

I did this for now as a temporary fix, not sure if this is best answer though.

$em = $this->em;

       $connection = $em->getConnection();
       $statement = $connection->prepare("
            SELECT apntoken,deviceid,created 
            FROM `distribution_mobiletokens` as dm
            WHERE userid=:userid
            and not exists (
                select 1 
                from `distribution_mobiletokens`
                where userid = :userid
                and deviceid = dm.deviceid
                and created > dm.created
            )");
       $statement->bindValue('userid', $jsondata['userid']);
       $statement->execute();

       $mobiletokens = $statement->fetchAll();

       //@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";
       }

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();
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM