如果我理解正确的话,如果已经有一行具有相同的首选语言,那么您想要“删除”具有后备语言的行slug
and title
.
您可以使用 LEFT JOIN 作为后备语言来检查是否存在具有首选语言的条目。例如,如果您的首选语言是“nl”并且后备语言是“en”,您的查询可能如下所示:
select blocks.*
from blocks
left join blocks b1
on b1.slug = blocks.slug
and b1.title = blocks.title
and b1.language = 'nl'
and blocks.language <> 'nl'
where blocks.slug = 'home'
and blocks.language in ('nl', 'en')
and b1.id is null
sqlfiddle
单词的连接可能是这样的:寻找相同的更好的翻译slug
and title
。如果该语言是首选语言,则不会匹配,因为blocks.language <> 'nl'
。否则,连接将“搜索”首选翻译('b1.language = 'nl'
).
在 WHERE 子句中,我们只告诉在没有找到更好的翻译的情况下返回行(b1.id is null
).
我能做的将查询转换为雄辩的最好方法是:
$prefered = 'nl';
$fallback = 'en';
$blocks = App\Block::where('blocks.slug', '=', 'home')
->whereIn('blocks.language', [$prefered, $fallback])
->leftJoin('blocks as b1', function($join) {
$join->on('b1.slug', '=', 'blocks.slug')
->on('b1.title', '=', 'blocks.title')
->on('b1.language', '=', DB::raw('?'))
->on('blocks.language', '<>', DB::raw('?'))
;
})
->whereNull('b1.id')
->addBinding([$prefered, $prefered], 'join')
->select(DB::raw('blocks.*'))
->get()
;
注意:我假设title
对于所有语言中的块来说都是相同的。否则你将需要另一列(例如block_id
)来识别一个块。