如何在 Doctrine2 (Symfony2) 中按案例排序

Posted

技术标签:

【中文标题】如何在 Doctrine2 (Symfony2) 中按案例排序【英文标题】:How to ORDER BY CASE in Doctrine2 (Symfony2) 【发布时间】:2013-12-27 15:20:09 【问题描述】:

我想在 Symfony 2.3 中使用 Doctrine 来运行这个查询。但似乎 Doctrine 不理解 CASE 声明。任何人都可以帮忙吗?提前谢谢!

SELECT max(id) id, name
FROM cards
WHERE name like '%John%'
GROUP BY name
ORDER BY CASE WHEN name like 'John %' THEN 0
           WHEN name like 'John%' THEN 1
           WHEN name like '% John%' THEN 2
           ELSE 3
      END, name

【问题讨论】:

一般来说,尽量不要将 DQL(Doctrine 的查询语言)与 SQL 混淆 - DQL 是它自己的方言,只是以不同的方式处理事情,这会使 case 的实现变得非常混乱至少。这样做的一个优点是它迫使您在更合适的其他地方执行类似 case 语句的业务逻辑。 【参考方案1】:

如果你使用 createQueryBuilder 那么你可以像这样使用

$query->addSelect("(CASE WHEN name like 'John %' THEN 0 当名字像 'John%' THEN 1 当名字像 '% John%' THEN 2 ELSE 3 END) 作为隐藏的 ORD"); $query->orderBy('ORD', 'DESC');

请注意,您必须拥有“隐藏”。

您也可以使用学说原生查询。

【讨论】:

感谢“隐藏”的东西 - 从来没有见过,但几年来我真的需要它 :) 学说在这种情况下将“ORD”的名称更改为“sclr16”。我能做什么? 值得一提的是,如果没有“ELSE”,“CASE”语句将无法正常工作。昨天我们挣扎了一个小时才弄明白为什么它不能那样工作:)【参考方案2】:

CASE 是特定于供应商的,学说本身不支持。

如果结果很小,我的建议是提取整个结果集然后对数组进行排序。

如果结果集太大,您应该编写本机查询并水合实体。有关这方面的更多信息,请参阅Doctrine Documentation on Native SQL。它看起来很吓人,但是一旦你通过一个例子就可以理解。

作为最后的手段,您可以绕过原则并使用低级原生 SQL。详情请见this post。

我知道Doctrine Extensions has an IfElse function 可能会奏效,但我没有听说过很多成功案例。

【讨论】:

@Benjamin 你的链接坏了 @PaoloStefan 更新链接:Doctrine 2 DQL 确实支持 CASE,请参阅 Case Expressions【参考方案3】:

我遇到了类似的问题,我必须在结果顶部添加一些数字前缀。 所以我这样解决:

    $qb = $this->createQueryBuilder('numberPrefix');
    $qb
        ->select('country.code','numberPrefix.prefix')
        ->addSelect('
            (CASE WHEN country.code = :firstCountryCode THEN 1
            WHEN country.code = :secondCountryCode THEN 2
            WHEN country.code = :thirdCountryCode THEN 3
            WHEN country.code = :fourthCountryCode THEN 4
            ELSE 5 END) AS HIDDEN ORD')
        ->innerJoin('numberPrefix.country','country')
        ->orderBy('ORD, country.id')
        ->setParameters(
            [
                'firstCountryCode' => $firstCountryCode,
                'secondCountryCode' => $secondCountryCode,
                'thirdCountryCode' => $thirdCountryCode,
                'fourthCountryCode' => $fourthCountryCode,
            ]
        );

【讨论】:

【参考方案4】:

如果不存在关系,则在按关系表或本地列排序时,这个可以为我完成这项工作:

$doctrineQuery->add('orderBy', '(CASE WHEN COUNT(relation_table.uid)>0 THEN relation_table.price ELSE current_table.generic_price END) ASC');

【讨论】:

以上是关于如何在 Doctrine2 (Symfony2) 中按案例排序的主要内容,如果未能解决你的问题,请参考以下文章

如何从 Symfony2 和 Doctrine2 中的一个点保存和检索纬度和经度

Symfony2 / Doctrine2:不要在模式上删除全文索引:更新

Symfony2 Doctrine2 获取所有表

带有 Symfony2 的 Doctrine2 无法识别数据库字符集和排序规则

Symfony2 项目中的 Doctrine2 映射问题

Doctrine2 自定义类型不像主键 Symfony2 那样工作