2016-08-23 92 views
3

我期待在laravel中减少我的查询大小。减少laravel中的数据库查询大小

我的查询看起来是这样的(我缩短了它,它是这一数额线的10倍左右):

$users = User::where("interface_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("interface_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1) 
->orWhere("web_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("web_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)      
->orWhere("illustration_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("illustration_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)     
->orWhere("brush_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("brush_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)     
->orWhere("typography_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("typography_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)     
->orWhere("identity_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("identity_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)     
->orWhere("vector_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) 
->orWhere("vector_art", '=', 1)->where('role', '=', 2)->where('commstatus', '=', 1)     
->orderBy($orderByString, 'desc') 
->paginate(1); 

正如你可以看到,这是一个有点多余。

对于每种艺术类型,如果它们的commstatus等于“1”或“$ unavailable”,我希望通过“2”角色获取用户。起初,我试图通过在每个“where”子句末尾添加“role”或“commstatus”来缩短它,并在底部编写另一个$ users = $ users :: where(“role” ,“=”,“2”),但我似乎无法找到正确的语法。

有什么办法可以缩短这个查询吗?

+5

它看起来就像你有一个违反[零,一个或无限规则](http://en.wikipedia.org/wiki/Zero_one_infinity_rule)的模式,需要进行重构以具有某种程度的[数据规范化](http:// en。 wikipedia.org/wiki/Database_normalization)。使用正确的模式,这个查询可能非常简单。 – tadman

+0

嗯,它工作得很好,我只是想缩短它,我似乎无法找到有效的语法。我试过在[documentation](https://laravel.com/docs/5.2/queries)中找到可能对我有用的东西,但我似乎无法找到任何东西。 –

+0

我希望'$ unavailableCheck'不代表NULL。如果是这样,你还有其他麻烦。 –

回答

3

正如其他人所指出的,你的模式可能会从实现正常化重构中受益。不过,我相信你仍然可以重构现有的查询,减少冗余并提高可读性。

Laravel有能力处理Advanced Where Clauses其中包括nested parameter groupings。从文档:

Closure将收到一个查询生成器实例,您可以使用它来设置应包含在括号组中的约束。

考虑到这一点,你应该能够重构像这样的查询:

$users = User::whereIn('commstatus', [$unavailableCheck, 1]) 
    ->where('role', 2) 
    ->where(function ($query) { 
     $query->where("interface_art", 1) 
      ->orWhere("web_art", 1) 
      ->orWhere("illustration_art", 1) 
      ->orWhere("brush_art", 1) 
      ->orWhere("typography_art", 1) 
      ->orWhere("identity_art", 1) 
      ->orWhere("vector_art", 1); 
    }) 
    ->orderBy($orderByString, 'desc') 
    ->paginate(1); 

这将创建一个SQL查询的作用:

SELECT * FROM users 
    WHERE commstatus IN ($unavailableCheck, 1) 
    AND role = 2 
    AND (interface_art = 1 OR illustration_art = 1 OR ... etc) 
+1

恭喜你,你赢了! –

4

对于每种艺术类型,您肯定不需要复制where('role', '=', 2)->where('commstatus', '=', $unavailableCheck),因为它们是有效的与条件;并考虑whereIn('commstatus', [$unavailableCheck, 1])而不是有两个平等检查。

喜欢的东西:

$users = User::where('role', '=', 2) 
    ->whereIn('commstatus', [$unavailableCheck, 1]) 
    ->where("interface_art", '=', 1) 
    ->orWhere("web_art", '=', 1) 
    ->orWhere("illustration_art", '=', 1) 
    ->orWhere("brush_art", '=', 1) 
    ->orWhere("typography_art", '=', 1) 
    ->orWhere("identity_art", '=', 1) 
    ->orWhere("vector_art", '=', 1) 
    ->orderBy($orderByString, 'desc') 
    ->paginate(1); 
+0

啊,我认为这工作,但它没有。 “角色”和“commstatus”仅适用于第一个where子句(在本例中为界面艺术)。所有其他wheres没有角色2或commstatus适用于他们。 –

+0

目的是获得一个SQL子句,它读取WHERE \'role \'= 2 AND \'commstatus \'IN($ unavailableCheck,1)AND(\'interface_art \'= 1 OR \'web_art \'= 1 OR \'illustration_art \'= 1 OR ...)'您是否启用了数据库调试日志记录来查看您实际获取的查询? –