如何在 Laravel Eloquent 中对子查询使用内部联接
How to use inner joins with subqueries in Laravel Eloquent
注意:这是laravel 5.3
基本上我是 运行 当用户选择阿拉伯语翻译时的查询。完整的 sql 看起来像这样
select s.ref, t.text as ref_ar
FROM stores AS s
INNER JOIN
(SELECT item, text
FROM translator_translations
WHERE locale ='ar'
AND namespace ='*'
AND item like 'store.ref%'
) AS t
ON substring(s.ref_translation from 14 for 26) = t.item;
在官方 Laravel 文档上没有看到太多关于子查询的文档(有内部连接的东西但不够好)而且 SO 建议似乎非常 hacky.. 建议?
上下文
这将用作模型内部的范围,因此这适用于例如:
public function scopeFilterLanguage($query, $language_id)
{
if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
return $query;
}
return $query->whereRaw("
substring(ref_translation from 14 for 26) in
(select item
from
translator_translations
where
locale ='ar' and namespace ='*'
and
item like 'store.ref%')");
}
但它没有给我想要的东西。 (即我必须在开头使用更大的版本 post)
这是我完全未经测试的最佳猜测结果。
public function scopeFilterLanguage($query, $language_id)
{
if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
return $query;
}
return $query->join('translator_translations', function($join) {
$join->selectSub(function($q) {
$q->where('t.locale' => 'ar')
$q->where('t.namespace', '*')
$q->where('t.item', 'like', $this->ref . '%')
}, 't');
})->on('t.item', '=', substr($this->ref_translation, 14, 26))
->select('t.text', 'ref');
}
这有效(忽略像 this->getClassName 等动态的东西)..基本逻辑工作得很好
public function scopeAddTranslations($query)
{
$t = new Translation();
$subq = $t->select('item','text as ref_ar')
->where('locale','=','ar')
->where('item','like',$this->getClassName().'.ref%');
$query->leftjoin(\DB::raw('('.$subq->toSql().') as t'),
function ($join) use ($subq) {
$join->on(\DB::raw('SUBSTRING('.$this->getTable().'.ref_translation
FROM 14 FOR 26)'),
'=',
\DB::raw('t.item'))
->addBinding($subq->getBindings());
});
return $query;
}
注意:这是laravel 5.3
基本上我是 运行 当用户选择阿拉伯语翻译时的查询。完整的 sql 看起来像这样
select s.ref, t.text as ref_ar
FROM stores AS s
INNER JOIN
(SELECT item, text
FROM translator_translations
WHERE locale ='ar'
AND namespace ='*'
AND item like 'store.ref%'
) AS t
ON substring(s.ref_translation from 14 for 26) = t.item;
在官方 Laravel 文档上没有看到太多关于子查询的文档(有内部连接的东西但不够好)而且 SO 建议似乎非常 hacky.. 建议?
上下文
这将用作模型内部的范围,因此这适用于例如:
public function scopeFilterLanguage($query, $language_id)
{
if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
return $query;
}
return $query->whereRaw("
substring(ref_translation from 14 for 26) in
(select item
from
translator_translations
where
locale ='ar' and namespace ='*'
and
item like 'store.ref%')");
}
但它没有给我想要的东西。 (即我必须在开头使用更大的版本 post)
这是我完全未经测试的最佳猜测结果。
public function scopeFilterLanguage($query, $language_id)
{
if (!$language_id || intval($language_id) != LanguageConstants::ARABIC_LANGUAGE_ID) {
return $query;
}
return $query->join('translator_translations', function($join) {
$join->selectSub(function($q) {
$q->where('t.locale' => 'ar')
$q->where('t.namespace', '*')
$q->where('t.item', 'like', $this->ref . '%')
}, 't');
})->on('t.item', '=', substr($this->ref_translation, 14, 26))
->select('t.text', 'ref');
}
这有效(忽略像 this->getClassName 等动态的东西)..基本逻辑工作得很好
public function scopeAddTranslations($query)
{
$t = new Translation();
$subq = $t->select('item','text as ref_ar')
->where('locale','=','ar')
->where('item','like',$this->getClassName().'.ref%');
$query->leftjoin(\DB::raw('('.$subq->toSql().') as t'),
function ($join) use ($subq) {
$join->on(\DB::raw('SUBSTRING('.$this->getTable().'.ref_translation
FROM 14 FOR 26)'),
'=',
\DB::raw('t.item'))
->addBinding($subq->getBindings());
});
return $query;
}