2013-12-17 5 views
0

У меня есть простой запрос, который выбирает сущности и использует оператор предельных значений. Я использую Doctrine NativeQuery, потому что у меня есть функция FIELD() в sql-запросе, и в результате мне нужен набор объектов. Этот запрос работает.Получить общее количество строк с помощью «SQL_CALC_FOUND_ROWS» и Doctrine NativeQuery

Однако мне нужно также общее количество записей, поэтому я использую SQL_CALC_FOUND_ROWS в первом запросе. После первого получения результата я создаю еще один ResultSetMapping, другой $ nativeQuery, выполните SELECT FOUND_ROWS() AS found_rows, и я получаю общее количество «1».

$rsm = new ResultSetMapping(); 

$rsm->addEntityResult('\\MyCompany\\Administration\\Domain\\Model\\Applicant\\Applicant', 'a'); 

$rsm->addFieldResult('a', 'first_name', 'firstName'); 
$rsm->addFieldResult('a', 'last_name', 'lastName'); 

$query = $this->em->createNativeQuery('SELECT SQL_CALC_FOUND_ROWS * FROM recruitment_applicant ORDER BY FIELD(id,5,15,8,17,2,1,16,9,7,11,6,10,12,13,14,18)', $rsm); 

$result = $query->getResult(); // this result is ok 



$sqlCountRows = "SELECT FOUND_ROWS() AS found_rows"; 

$countRowsRsm = new ResultSetMapping(); 

$countRowsRsm->addScalarResult('found_rows', 'foundRows'); 

$countRowsQuery = $this->em->createNativeQuery($sqlCountRows,$countRowsRsm); 

$rowsCount = $countRowsQuery->getResult(); 

$total = $rowsCount[0]['foundRows']; // result is '1' when it should be '16' 

Я использовал this пример.

ответ

2
  1. Вам не нужно использовать собственный запрос. FIELD() действительно очень легко реализовать в виде функции пользовательского DQL:

    1. Читать DQL User Defined Functions и How to Register Custom DQL Functions на Doctrine/Symfony документации.
    2. FIELD() реализация:

      use Doctrine\ORM\Query\AST\Functions\FunctionNode; 
      use Doctrine\ORM\Query\Lexer; 
      use Doctrine\ORM\Query\Parser; 
      use Doctrine\ORM\Query\SqlWalker; 
      
      class Field extends FunctionNode 
      { 
          private $field = null; 
          private $values = array(); 
      
          public function parse(Parser $parser) 
          { 
           $parser->match(Lexer::T_IDENTIFIER); 
           $parser->match(Lexer::T_OPEN_PARENTHESIS); 
      
           $this->field = $parser->arithmeticPrimary(); 
      
           while (count($this->values) < 1 || $parser->getLexer()->lookahead['type'] !== Lexer::T_CLOSE_PARENTHESIS) { 
            $parser->match(Lexer::T_COMMA); 
            $this->values[] = $parser->arithmeticPrimary(); 
           } 
      
           $parser->match(Lexer::T_CLOSE_PARENTHESIS); 
          } 
      
          public function getSql(SqlWalker $sqlWalker) 
          { 
           $values = array(); 
           foreach ($this->values as $value) { 
            $values[] = $value->dispatch($sqlWalker); 
           } 
      
           return sprintf('FIELD(%s, %s)', $this->field->dispatch($sqlWalker), implode(', ', $values)); 
          } 
      } 
      
  2. Вам не нужно событие отсчета запроса. Однако, если вам нужен запрос COUNT(*), вы можете легко клонировать ваш исходный запрос и использовать CountWalker, чтобы создать запрос подсчета из запроса выбора.

0

Я выяснил, что может быть причиной проблемы: профилировщик Symfony2, раздел запросов, показывает всего 22 выполненных запроса. Мой первый запрос запускается третий подряд, а мой второй запрос, тот, который возвращает количество строк, будет исполнен 13-м. SQL_CALC_FOUND_ROWS работает, если SELECT FOUND_ROWS() запускается сразу после первого запроса.

Смежные вопросы