如何在 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:不要在模式上删除全文索引:更新