Search code examples
phpsymfonydoctrine-ormdqlquery-builder

Doctrine error when using SUM(a.id=1) as `ìdentifier`: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '='


I am trying to execute a query in doctrine that contains something like this

SUM(a.id = 1) as `1`

for some reasons it always gives me the following error:

[Syntax Error] line 0, col 15: Error: Expected Doctrine\ORM\Query\Lexer::T_CLOSE_PARENTHESIS, got '='

This is the code i am using

 $result = $em->getRepository('MyBundle:PlayerAction')
            ->createQueryBuilder('pa')
            ->select(array(
                'SUM(a.id=1) as `1`,
                SUM(a.id=2) as `2`,
                SUM(a.id=3) as `3`,
                p.playerName,
                pa.timestamp'
            ))
            ->innerJoin('pa.action', 'a')
            ->innerJoin('pa.player', 'p')
            ->where('pa.timestamp > ?1')
            ->groupBy('p')
            ->setParameter(1, time() - $time)
            ->orderBy('p.playerName', 'ASC');

Solution

  • Considering the error message, it appears Doctrine does some parsing of its own on your MySQL expressions. As already suggested by nietonfir, this parser may not be fully compliant to MySQL's. You could try some syntactic variations, for example:

    SUM(CASE a.id WHEN 1 THEN 1 ELSE 0 END) as `1`,
    SUM(CASE a.id WHEN 2 THEN 1 ELSE 0 END) as `2`,
    SUM(CASE a.id WHEN 3 THEN 1 ELSE 0 END) as `3`
    

    or:

    SUM(IF(a.id=1, 1, 0)) as `1`,
    SUM(IF(a.id=2, 1, 0)) as `2`,
    SUM(IF(a.id=3, 1, 0)) as `3`
    

    If that fails, refactor the query; something along this line (just thinking out loud here; I'll leave the QueryBuilder equivalent up to you):

    SELECT
       (SELECT COUNT(*) FROM PlayerAction AS pa WHERE pa.player = p.id AND pa.timestamp > ?1 AND pa.action = 1) AS `1`,
       (SELECT COUNT(*) FROM PlayerAction AS pa WHERE pa.player = p.id AND pa.timestamp > ?1 AND pa.action = 2) AS `2`,
       (SELECT COUNT(*) FROM PlayerAction AS pa WHERE pa.player = p.id AND pa.timestamp > ?1 AND pa.action = 3) AS `3`,
       p.playerName
    FROM Player p
    ORDER BY p.playerName ASC
    

    This may negatively affect query performance.