1

New to Doctrine and trying to convert the MySQL query below to queryBuilder.

SELECT COUNT(t2.user_id) FROM(
    SELECT t2.* FROM logins t2
        WHERE t2.login_time >= DATE_SUB(NOW(),INTERVAL 5 HOUR)
        LIMIT 10
    ) t2
WHERE t2.is_success = 1

I've seen a few examples of subquery on the WHERE clause here on SO and attempted to adapt it as per below, but that does not really work.

        $sub = $this->createQueryBuilder('l')
        ->select('l')
        ->where('l.loginTime >= :date
            and l.userId = :user_id')
        ->setParameters( $parameters )
        ->getDQL();

    $qb = $this->createQueryBuilder('a')
        ->select('count(a.id)')
        ->from( $sub, 'a' )
        ->where('a.isSuccess = 0'); 
    return $qb->getQuery()->getSingleScalarResult(); 

Thanks

Paulie-C
  • 1,674
  • 1
  • 13
  • 29
BernardA
  • 1,391
  • 19
  • 48

2 Answers2

0

Use this query,

$date = new Doctrine_Expression('DATE_SUB(NOW() , INTERVAL 5 HOUR)');
$query
->select('count(t2.userId)')
->from('Login', 't2')
->where('t2.loginTime >= :date')
->andWhere('t2.isSuccess = 1')
->setParameter('date',$date);
->setMaxResults(10);    
Viraj Amarasinghe
  • 911
  • 10
  • 20
0

As @colburton pointed out, it seems that Doctine isn't able to handle subqueries as such. Check this post.

So, I am posting the possible solutions I've found and hopefully somebody will correct me or improve on it.

Alternative 1 - Though I did not verify it, it seems that Native SQL would be able to handle it. Downside is that it seems quite complex, particularly when there are more sensible alternatives.

Alternative 2 - Run plain old mySQL query. Given that the result is a scalar that would be just fine. This is how I set it up.

UsedBundle/Repository/LoginRepository.php

public function countAllFailedMysqlAction()
{
    $ulink = new \PDO("mysql:host=$hostname;dbname=$database;charset=utf8", $username, $password);
    $sql = "SELECT COUNT(t2.user_id) FROM(
        SELECT t2.* FROM logins t2
        WHERE t2.login_time >= DATE_SUB(NOW(),INTERVAL 5 HOUR)
        LIMIT 10
        ) t2
        WHERE t2.is_success = 0";
        $stmt = $ulink->query($sql); 
        return $stmt->fetchColumn();
}

Alternative 3 - In this particular instance, one could just run the inner or subquery using regular Entity, return an array and iterate through it to get the result.

UsedBundle/Repository/LoginRepository.php

public function countAllFailedAction()
{
    $date = new \DateTime();
    $date->modify('-24 hour');

    $qb = $this->createQueryBuilder('l')
        ->select('l.id,l.isSuccess')
        ->where('l.loginTime >= :date')
        ->setParameter('date', $date)
        ->setMaxResults(10);
    $logins = $qb->getQuery()->getArrayResult();

    $ct_failed = 0;
    foreach( $logins as $login ){
        if($login['isSuccess'] == false ){ $ct_failed++;}
    }
    return $ct_failed;        
}
BernardA
  • 1,391
  • 19
  • 48