在使用querybuilder的语言字段上,主义优先左联接

时间:2019-04-16 19:26:08

标签: symfony join doctrine left-join query-builder

我正在使用以下查询:

use Doctrine\ORM\Query\Expr\Join;

$query = $this->createQueryBuilder('ad')
    ->select('ad.id, ad.title, ad.year, ad.hours, ad.status')
    ->addSelect('rem.remark')
    ->leftJoin('ad.remark', 'rem', Join::WITH, "rem.language = 'NL'")
    ->getQuery()
    ->getResult();

此查询工作正常,并以荷兰语返回广告的备注。该广告与备注具有一对多关系。

只有我也有带有英文备注而不是荷兰语的广告。我想得到该评论的英文说明,列表中的其他评论仍为荷兰语。因此,也要总结一下对返回的语言的优先级列表吗?

1 个答案:

答案 0 :(得分:0)

解决此问题的一种方法是使用额外的join without relation

$query = $this->createQueryBuilder('ad')
    ->select('ad.id, ad.title, ad.year, ad.hours, ad.status')
    ->addSelect('rem.remark')
    ->leftJoin('ad.remark', 'rem', Join::WITH, "rem.language = 'NL' OR rem.language = 'EN'")
    ->leftJoin(Remark::class, 'customRem', Join::WITH, 
    "rem.id <> customRem.id 
    AND rem.ad = customRem.ad 
    AND customRem.language = 'NL'")
    ->where('customRem.id IS NULL')
    ->getQuery()
    ->getResult();

这个想法是

  • 如果广告存在NL语言注释,请将此注释添加到该广告期望的每个结果行中(本身为空)
  • 如果不存在NL语言注释且EN存在,则连接的行将为空

最后,条件customRem.id IS NULL使这项工作得以实现。

多种语言解决方案

对于3种受支持的语言,由于 DE> EN> NL ,您可以执行以下操作:

->leftJoin(Remark::class, 'customRem', Join::WITH,        
     "rem.id <> customRem.id AND rem.ad = 
      customRem.ad AND rem.language < customRem.language")

对于多种语言,并假设具有“ 自定义”订购语言的能力,则可以使用:

"rem.id <> customRem.id 
AND rem.ad = customRem.ad AND 
(case when rem.language = 'NL' THEN 3 " .
"when rem.language = 'EN' THEN 2 " .
"when rem.language = 'DE' THEN 1 ELSE 0 END) < (case when customRem.language = 'NL' THEN 3 " .
"when customRem.language = 'EN' THEN 2 " .
"when customRem.language = 'DE' THEN 1 ELSE 0 END)"

或者,您可以创建“ lang_position”表(ID,语言,位置),然后两次联接以从语言中获取位置。