2016-08-23 2 views
3

Ich möchte die Größe meiner Abfrage in Laravel reduzieren.Reduzieren von Datenbankabfragegrößen in Laravel

Meine Abfrage sieht wie folgt aus etwas (ich es verkürzt, es geht um das 10-fache dieser Menge von Linien):

$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); 

Wie Sie sehen können, ist es ein wenig überflüssig ist.

Für jeden Kunsttyp, ich suche Benutzer nach der Rolle von "2", wenn ihre Kommastatus gleich "1" oder "nicht verfügbar" ist.

Zuerst versuchte ich es zu kürzen, indem ich am Ende jeder "where" -Klausel keine "role" oder "commstatus" hinzufügte, und am unteren Rand einen weiteren $ users = $ users :: wo ("role") , "=", "2"), aber ich kann nicht in der Lage sein, die richtige Syntax zu finden.

Gibt es eine Möglichkeit, diese Abfrage zu verkürzen?

+5

Es sieht aus wie Sie haben hat ein Schema erhalten, das die [Null, eine oder Unendlichkeitsregel] verletzt (http://en.wikipedia.org/wiki/Zero_one_infinity_rule) und neu strukturiert werden muss, um ein gewisses Maß an [Datennormalisierung] zu haben (http: // en. wikipedia.org/wiki/Datenbank_normierung). Mit dem richtigen Schema könnte diese Abfrage ziemlich einfach sein. – tadman

+0

Nun, es funktioniert ganz gut, ich möchte es nur kürzen, ich kann einfach nicht finden, Syntax, die funktioniert. Ich habe versucht, etwas in der [Dokumentation] (https://laravel.com/docs/5.2/queries) zu finden, das mir helfen könnte, aber ich kann nichts finden. –

+0

Ich hoffe, '$ availableCheck' repräsentiert nicht' NULL'. Wenn ja, hast du andere Probleme. –

Antwort

3

Wie andere gesagt haben, würde Ihr Schema profitieren wahrscheinlich von der Normalisierung Refactoring. Ich glaube jedoch, dass Sie Ihre vorhandene Abfrage immer noch als weniger redundant und lesbarer gestalten können.

Laravel hat die Fähigkeit, Advanced Where Clauses zu behandeln, die nested parameter groupings einschließen. Aus der Dokumentation:

Die Closure wird eine Query Builder-Instanz erhalten, mit der Sie die Einschränkungen festlegen können, die in der Klammergruppe enthalten sein sollen.

$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); 

, die eine SQL-Abfrage erstellen wird, das tut:

, die mit im Auge, sollten Sie die Abfrage wie folgt Refactoring der Lage sein,

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

Herzlichen Glückwunsch, Sie gewinnen! –

4

Sie sollten nicht unbedingt where('role', '=', 2)->where('commstatus', '=', $unavailableCheck) für jede Art von Kunst duplizieren müssen, da sie effektiv UND-Bedingungen sind; und betrachte whereIn('commstatus', [$unavailableCheck, 1]) anstelle von zwei Gleichheitsüberprüfungen.

Etwas wie:

$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

Ah, ich dachte, das funktioniert, aber es hat nicht funktioniert. Die "Rolle" und "Kommastatus" werden nur auf die erste Where-Klausel (in diesem Fall Interface-Art) angewendet. Alle anderen Positionen haben keine Rolle 2 oder commstatus, die auf sie angewendet werden. –

+0

Ziel ist es, eine SQL-Klausel zu erhalten, die 'WHERE \' role \ '= 2 UND \ commstatus \' IN ($ availableCheck, 1) UND (\ 'interface_art \' = 1 ODER \ 'web_art \ '= 1 liest ODER \ Illustration_art \ '= 1 OR ...)' Haben Sie die Datenbank-Debug-Protokollierung aktiviert, um die Abfrage zu sehen, die Sie tatsächlich bekommen? –