Laravel - Eloquent - 预先加载 - 约束/选择/分组
Laravel - Eloquent - Eager Loading - Constraints / Selection / Grouping
我发现 Eloquent 的连接逻辑比典型的准备语句复杂得多(我讨厌它)。
有人可以帮我将以下查询翻译成一个 完全 急切加载的合理 eloquent 查询吗?
SELECT C.id,
C.seo_alias
FROM store_variants AS A
LEFT JOIN variants AS B ON B.id = A.id_variant
LEFT JOIN products AS C ON C.id = B.id_product
LEFT JOIN stores AS D ON D.id = A.id_store
WHERE D.id = 123
AND A.isActive > 0
GROUP BY C.id;
一种产品 - 多种变体
一个变体 - 许多商店
一个 store_variant - 一个商店
模型是 storeVariantModel、variantModel、productModel、storeModel。有数百万行。
在我看来,这个查询包含过滤select离子、连接、分组和约束,所以它涵盖了我日常遇到的大部分操作,所以如果有人能解决这个问题,我衷心感谢.
谢谢
编辑:使用Laravel 5.2
编辑:解决方案 #2:
感谢@Balraj 的帮助,这基本上是我被迫使用的最终解决方案:
storeVariantModel::
join( 'variants', 'variants.id_variant', '=', 'store_variants.id')
->join( 'products', 'products.id', '=', 'variants.id_product')
->join( 'stores', 'stores.id', '=', 'store_variants.id_store')
->with([
'variantModel.storeVariantModel.storeModel',
'variantModel.productModel'
])
->select('variants.*')
->where('stores.id','=',123)
->where('store_variants.isActive','>',0)
->get();
修改:我不再使用 'GROUP BY'
优点:我得到了带有关系的模型,对中间表的约束过滤数据,而不是只急切加载与约束匹配的任何数据
缺点:语法是球,我基本上调用了两次连接,我不再对一组有限的列进行 select
试试这个,
storeVariantModel::join('variants.id_variant','=','store_variants.id')
->join('products','products.id','=','variants.id_product')
->join('stores','stores.id','=','store_variants.id_store')
->select(['products.id','products.seo_alias'])
->where('stores.id','=',123)
->where('store_variants.isActive','>',0)
->groupby('products.id')
->get();
更新答案
Eloquent 没有 groupby:
In productModel:
public function variants(){
return $this->hasMany(variantModel::class,'id_product','id');
}
In variantModel:
public function store_variants(){
return $this->hasMany(storeVariantModel::class,'id_variant','id);
}
In storeVariantModel:
public function stores(){
return $this->hasOne(storeModel::class,'id','id_store');
}
productModel::with(['variants.store_variants.stores' => function($q){
$q->where('id','=',123);
}])->whereHas('variants.store_variants', function($q){
$q->where('isActive','>',0);
})->get();
按照你的描述,C有很多B,B有很多A,D有很多A。
你可以像这样用约束预先加载它们
$result = CModel::with(['BRelationship' => function ($query) {
$query->with(['ARelationship' => function ($sub1) {
$sub1->with(['DRelationship' => function($sub2) {
$sub3->where('id', '123);
}]);
}])->where('condition') //to add extra condition if you want
->groupBy('column'); //if you want to group by in ARelationship
}])->get();
你可以读作 C with B with A with D。
我还没有测试过这段代码,祝你好运。也不要忘记正确定义关系。
我发现 Eloquent 的连接逻辑比典型的准备语句复杂得多(我讨厌它)。
有人可以帮我将以下查询翻译成一个 完全 急切加载的合理 eloquent 查询吗?
SELECT C.id,
C.seo_alias
FROM store_variants AS A
LEFT JOIN variants AS B ON B.id = A.id_variant
LEFT JOIN products AS C ON C.id = B.id_product
LEFT JOIN stores AS D ON D.id = A.id_store
WHERE D.id = 123
AND A.isActive > 0
GROUP BY C.id;
一种产品 - 多种变体
一个变体 - 许多商店
一个 store_variant - 一个商店
模型是 storeVariantModel、variantModel、productModel、storeModel。有数百万行。
在我看来,这个查询包含过滤select离子、连接、分组和约束,所以它涵盖了我日常遇到的大部分操作,所以如果有人能解决这个问题,我衷心感谢.
谢谢
编辑:使用Laravel 5.2
编辑:解决方案 #2:
感谢@Balraj 的帮助,这基本上是我被迫使用的最终解决方案:
storeVariantModel::
join( 'variants', 'variants.id_variant', '=', 'store_variants.id')
->join( 'products', 'products.id', '=', 'variants.id_product')
->join( 'stores', 'stores.id', '=', 'store_variants.id_store')
->with([
'variantModel.storeVariantModel.storeModel',
'variantModel.productModel'
])
->select('variants.*')
->where('stores.id','=',123)
->where('store_variants.isActive','>',0)
->get();
修改:我不再使用 'GROUP BY'
优点:我得到了带有关系的模型,对中间表的约束过滤数据,而不是只急切加载与约束匹配的任何数据
缺点:语法是球,我基本上调用了两次连接,我不再对一组有限的列进行 select
试试这个,
storeVariantModel::join('variants.id_variant','=','store_variants.id')
->join('products','products.id','=','variants.id_product')
->join('stores','stores.id','=','store_variants.id_store')
->select(['products.id','products.seo_alias'])
->where('stores.id','=',123)
->where('store_variants.isActive','>',0)
->groupby('products.id')
->get();
更新答案
Eloquent 没有 groupby:
In productModel:
public function variants(){
return $this->hasMany(variantModel::class,'id_product','id');
}
In variantModel:
public function store_variants(){
return $this->hasMany(storeVariantModel::class,'id_variant','id);
}
In storeVariantModel:
public function stores(){
return $this->hasOne(storeModel::class,'id','id_store');
}
productModel::with(['variants.store_variants.stores' => function($q){
$q->where('id','=',123);
}])->whereHas('variants.store_variants', function($q){
$q->where('isActive','>',0);
})->get();
按照你的描述,C有很多B,B有很多A,D有很多A。
你可以像这样用约束预先加载它们
$result = CModel::with(['BRelationship' => function ($query) {
$query->with(['ARelationship' => function ($sub1) {
$sub1->with(['DRelationship' => function($sub2) {
$sub3->where('id', '123);
}]);
}])->where('condition') //to add extra condition if you want
->groupBy('column'); //if you want to group by in ARelationship
}])->get();
你可以读作 C with B with A with D。
我还没有测试过这段代码,祝你好运。也不要忘记正确定义关系。