Как использовать интервал в Doctrine2 Query Builder

В моем репозитории Symfony2 я хотел бы получить объекты из таблицы расписания, которые были запущены, но еще не завершены. Интервал внутри объектов должен рассматриваться как «незавершенный», его следует передавать как переменную.

Используя простой SQL, это работает так:

SELECT * FROM slots rbs 
  WHERE rbs.rundate = '2012-08-13' 
  AND rbs.runtime <= '11:05:00' 
  AND '11:05:00' <= rbs.runtime + interval '300 seconds'
  ORDER BY rbs.rundate DESC, rbs.runtime DESC

Могу ли я добиться того же с помощью DQL / Query Builder?

Вот что у меня есть на данный момент:

$qb = $this->createQueryBuilder('rbs');
$qb->where(
    $qb->expr()->andX(
         $qb->expr()->eq('rbs.rundate', ':date'),
         $qb->expr()->lte('rbs.runtime', ':time'),
         'rbs.runtime + interval 300 seconds >= :time'
        )
    )
  ->orderBy('rbs.rundate', 'DESC')
  ->addOrderBy('rbs.runtime', 'DESC')
  ->setParameter('date', date('Y-m-d'))
  ->setParameter('time', date('H:i:s'))

Но это возвращает следующую ошибку:

[Doctrine\ORM\Query\QueryException]                                                 
[Syntax Error] line 0, col 139: Error: Expected =, <, <=, <>, >, >=, !=, got '300'

Я обнаружил, что 'interval' не поддерживается Doctrine2 / DQL, который также упоминается здесь.

Любые предложения о том, как сделать это с помощью Doctrine2 Query Builder или DQL (и передачи интервала как переменной)?


person mediafreakch    schedule 13.08.2012    source источник


Ответы (3)


Насколько мне известно, Interval не портируется в Doctrine. Обходной путь, который я нашел, - работать непосредственно с DateTime, который я передаю в качестве параметра (здесь я хотел бы использовать интервал в 2 дня, передаваемый через Datetime):

public function findOngoingPublicEvents()
{
    return $this->createQueryBuilder('e')
        ->where('e.isActive = 1')
        ->andWhere('e.isPublic = 1')
        ->andWhere('e.begin <= :begin')
        ->andWhere('e.end >= :end')
        ->orderBy('e.id', 'ASC')
        ->setParameter('begin', new \DateTime('+2 days'))
        ->setParameter('end', new \DateTime('-2 days'))
        ->getQuery()
        ->execute();
}
person guillaumepotier    schedule 13.08.2012
comment
Спасибо, подсказка с \ DateTime у меня сработала. Хотя у меня есть только поле времени выполнения, мне пришлось использовать его так: ->where('rbs.runtime <= :now') ->andWhere('rbs.runtime >= :xbefore') ->setParameter('now', new \DateTime()) ->setParameter('xbefore', new \DateTime('-300 seconds') Вы даже можете заменить жестко запрограммированное значение для \ DateTime переменной: new \DateTime('-'.$tolerance.' seconds') - person mediafreakch; 14.08.2012
comment
Оно работает. Как насчет использования значения из столбца в качестве смещения времени? Что-то вроде ->setParameter('begin', new \DateTime('+e.timeOffset days')). Как я могу этого добиться? - person Ramon Dekkers; 30.09.2013
comment
Многие из тех же функций, для которых вы используете INTERVAL в PgSQL, вы можете переписать с помощью функций Doctrine DQL: DATE_ADD (), DATE_SUB (), DATE_DIFF () - также проверьте CURRENT_DATE (), CURRENT_TIME () и CURRENT_TIMESTAMP (). Вот как я решил проблему. Если вы углубитесь в код Doctrine, DQL использует для этого интервалы psql. - person davmor; 06.11.2014

Если вы хотите использовать ИНТЕРВАЛ (в Doctrine 2, DQL) в поле столбца mysql, вы можете использовать, как показано ниже,

$qb->andWhere("DATE_ADD(pv.myDAte,48,'hour') >= UTC_TIMESTAMP()");

Он напечатает SQL, как показано ниже,

...... DATE_ADD(p0_.appointment_date, INTERVAL 48 HOUR) >= UTC_TIMESTAMP() .....
person Kiran    schedule 11.04.2019

@Kiran пишите только о DATE_ADD, но вы также можете использовать DATE_SUB

$qb->andWhere("DATE(a2_.updatedAt) = DATE_SUB(CURRENT_DATE(), 6, 'day')");

Это эквивалент SQL:

DATE(a2_.updatedAt) = DATE_SUB(CURRENT_DATE, INTERVAL 6 DAY)
person Serhii Popov    schedule 18.04.2019
comment
Я использую DATE_ADD(a.lastConnectionDate, 1, 'month') <= NOW() в моем queryBuilder - person NBoulfroy; 17.02.2021