Порядок учений по сложному выражению - PullRequest
0 голосов
/ 17 мая 2018

Я хочу повторить следующий запрос, который сортирует всех пользователей по имени, но те, чьи имена начинаются с Z, идут первыми:

SELECT *
FROM user
ORDER BY LEFT(name, 1) != 'Z', name

У меня есть это:

$qb = $this->getEntityManager()->createQueryBuilder();
$qb->select('u')
    ->addSelect($qb->expr()->neq($qb->expr()->substring('u.name', 1, 1), $qb->expr()->literal('Z')) . ' AS HIDDEN firstLetterIsNotZ')
    ->from(user::class, 'u')
    ->orderBy('firstLetterIsNotZ')
    ->addOrderBy('u.name');

сгенерированный DQL выглядит достаточно вменяемым:

SELECT s, SUBSTRING(u.name, 1, 1) <> 'Z' AS HIDDEN descriptionFirstLetter
FROM user u
ORDER BY firstLetterIsNotZASC, s.description ASC

Но лексеру это не нравится: Error: Expected Doctrine\ORM\Query\Lexer::T_FROM, got '<'

1 Ответ

0 голосов
/ 17 мая 2018

Doctrine плохо обрабатывает условия внутри оператора select.

Вы можете обойти проблему, обернув свое состояние CASE WHEN, чтобы получить желаемый результат.

Я также параметризовал условие письма, чтобы оно было более переносимым, если вы хотите добавить его в качестве динамического значения.

$em = $this->getEntityManager();
$expr = $em->getExpressionBuilder();
$q = $em->createQueryBuilder()
    ->select('u')
    ->addSelect('(CASE WHEN ' . $expr->neq($expr->substring('u.name', 1, 1), ':letter') . ' THEN 0 ELSE 1 END) AS HIDDEN firstLetterIsNotZ')
    ->from(user::class, 'u')
    ->orderBy('firstLetterIsNotZ')
    ->addOrderBy('u.name')
    ->setParameter('letter', 'Z')
    ->getQuery();

dump($q->getDQL());
dump($q->getResult());

Результирующий DQL

SELECT u, (CASE WHEN SUBSTRING(u.name, 1, 1) <> :letter THEN 1 ELSE 0 END) AS HIDDEN firstLetterIsNotZ 
FROM user u 
ORDER BY firstLetterIsNotZ ASC, u.name ASC

Результирующие данные: (firstLetterIsNotZ не скрыт) * ​​1013 *

array:3 [▼
  0 => array:2 [▼
    0 => User {#2163 ▶}
    "firstLetterIsNotZ" => "0"
  ]
  1 => array:2 [▼
    0 => User {#2167 ▶}
    "firstLetterIsNotZ" => "1"
  ]
  2 => array:2 [▼
    0 => User {#2168 ▶}
    "firstLetterIsNotZ" => "1"
  ]
]
...