【问题标题】:Doctrine order by compound expression复合表达的教义顺序
【发布时间】:2018-10-27 03:12:36
【问题描述】:

我想复制以下查询,该查询按名称对所有用户进行排序,但名称以 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 '&lt;'

【问题讨论】:

    标签: php doctrine-orm doctrine-query


    【解决方案1】:

    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 not HIDDEN)

    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"
      ]
    ]
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-02-28
      • 1970-01-01
      • 2012-09-20
      • 1970-01-01
      • 2010-11-08
      • 2012-12-23
      相关资源
      最近更新 更多