2017-12-13 6 views
1

Der Zweck meiner Anwendung ist es, Gehaltsabrechnung Daten nach Abteilung, Datum (täglich, wöchentlich, monatlich, vierteljährlich und jährlich) zu knacken und es in einem Dashboard mit Grafiken anzuzeigen.Laravel Eloquent Abfrageoptimierung

Ich habe zwei (2) Tabellen, die ich CSV-Upload-Daten zu erhalten: 'Teilnahme' und 'Lohnsumme';

Ich habe zehn (10) Schulen jeweils durch eine vier (4) stellige Zahl in einem Textfeld identifiziert.

**attendance** = date | school_code | department_name | child_count 

**payroll** = date | school_code | teacher_name | department | hours | pay_rate 

Hier ist, was ich versuche. Meine Anfragen sind furchtbar teuer.

public function index() { 

    $schools  = array('1001', '1003', '1004', '1005', '1007', '1008', '1009', '1010', '1011'); 

    $infants = 'Infants'; 
    $ones  = 'Ones'; 
    $twos  = 'Twos'; 
    $threes = 'Threes'; 
    $fours  = 'Fours'; 
    $fives  = 'Fives'; 
    $schoolAge = 'School Age'; 
    $unknowns = 'Unknown'; 
    $preK  = 'PreK'; 
    $office = 'Office'; 

    $oneInfants = ChildCount::where('school_code', $schools[0])->where('department_name', $infants); 
    $oneOnes  = ChildCount::where('school_code', $schools[0])->where('department_name', $ones)->get(); 
    $oneTwos  = ChildCount::where('school_code', $schools[0])->where('department_name', $twos)->get(); 
    $oneThrees  = ChildCount::where('school_code', $schools[0])->where('department_name', $threes)->get(); 
    $oneFours  = ChildCount::where('school_code', $schools[0])->where('department_name', $fours)->get(); 
    $oneFives  = ChildCount::where('school_code', $schools[0])->where('department_name', $fives)->get(); 
    $oneSchoolAges = ChildCount::where('school_code', $schools[0])->where('department_name', $schoolAge)->get(); 
    $oneUnknowns = ChildCount::where('school_code', $schools[0])->where('department_name', $unknowns)->get(); 
    $onePreK  = ChildCount::where('school_code', $schools[0])->where('department_name', $preK)->get(); 
    $oneOffice  = ChildCount::where('school_code', $schools[0])->where('department_name', $office)->get(); 


... **REPEATED FOR EACH SCHOOL** ... 


    $oneMaster= DB::table('payrolls') 
        ->join('child_counts', 'child_counts.school_code', '=', 'payrolls.school_code') 
        ->where('payrolls.department', $infants) 
        ->where('payrolls.school_code',$schools[0]) 
        ->take(100) 
        ->select('payrolls.*', 'child_days') 
        ->get(); 

Ich habe nicht ein Modell für Schulen, weil dies eine Drittanbieter-Anwendung mit den Daten werden CSV aus unserem Hauptbetriebsprogramm exportiert.


Wie optimiere ich diese Abfragen, während auf school_code zwischen child_counts & & Payrolls Beitritt - sobald ich in der Lage bin durch diese Schulen, Abteilungen zu durchlaufen, und Termine - ich täglich abfragen kann, wöchentlich, monatlich, vierteljährlich und jährlich;

Vielen Dank im Voraus.

Antwort

1

Sie profitieren, wenn Sie für jede Datenbanktabelle ein aktuelles Eloquent-Modell verwenden (erstellen Sie ein Modell für Gehaltsabrechnungen, falls Sie noch kein solches besitzen). Wenn Sie das Payroll Modell haben, stellen Sie sicher, dass die entsprechenden relationship functions für jedes Modell definiert sind. (Machen Sie eine Beziehung auf ChildCount und um Ihr Leben später leichter zu machen, definieren Sie auch die umgekehrte Beziehung auf Payroll).

ChildCount.php

public function payrolls() { 
    return $this-hasMany(Payroll::class, 'school_code', 'school_code'); 
} 

// I think you can even limit the payrolls in your relationship, not sure about this 
public function payrollsLimited() { 
    return $this-hasMany(Payroll::class, 'school_code', 'school_code')->limit(100); 
} 

Auf diese Weise können eager loading nutzen können. Dies sollten Sie den Einstieg:

$schoolCode = $schools[0]; 
$departmentNames = [$infants, $ones, $twos, $threes]; // etc. 
$childCounts = ChildCount::where('school_code', $schoolCode) 
    ->whereIn('department_name', $departmentNames) 
    ->with(['payrolls']) // assumes the ChildCount model has a relationship with the payroll model 
    ->get(); 

Die oben in einem foreach gewickelt werden kann, über jede Schule in einer Schleife, aber natürlich können Sie alle Daten für jede Schule in einer Abfrage als auch laden. Ich weiß nicht, wie viele Schulen wir sprechen, oder wie groß Ihre Gehaltsliste ist, aber wenn Sie das versuchen möchten, würden Sie whereIn anstelle von where verwenden.

Viel Glück!

PS: Letzte Sache, die ich hinzufügen möchte, ist, möchten Sie möglicherweise einen anderen Blick auf Ihre Datenbank-Design oder Modellnamen. Es macht keinen Sinn für mich, dass die payrolls und childcounts Tabellen über school_code verbunden sind (und ist ChildCount der beste Name für Ihr Modell?)

+0

Danke Pepijn. Ihre Antwort ist gründlich, informativ und wies mich in eine viel bessere Richtung. – KSails

+0

Könnten Sie einen Vorschlag machen, wie Sie den Gehaltslisten und den Child_Counts beitreten können? Ich nehme an, dass ich ein ** School ** Modell machen sollte - ** school_code ** und ein ** date ** Feld sind meine gemeinsamen Felder mit denen ich arbeiten kann. Auf welches Feld sollte ich mich anmelden? Wir haben neun (9) Schulen und Gehaltsabrechnungs-/Anwesenheitsdaten, die zwei (2) Jahre zurückreichen - aufwärts von apprx. 120.000 Datensätze: | Danke, schon wieder! – KSails

+0

Kein Problem, froh zu helfen! Ja, im Idealfall würden Sie ein 'School'-Modell erstellen (das eine 'schools'-Datenbanktabelle benötigt, so dass Sie Ihren csv in diese [neue Tabelle] importieren müssen (https://laravel.com/docs/5.5/ Migrationen), zum Beispiel mit einem [Seeder] (https://laravel.com/docs/5.5/seeding)). Nachdem Sie die Beziehungen zu 'School' hinzugefügt haben, können Sie einfach 'School :: with ([' payrolls ',' childcounts ']) umkehren -> get()'. In diesem umstrukturierten Szenario sollten "Payroll" und "ChildCount" wahrscheinlich keine Beziehung mehr zueinander haben, da sie beide mit der Schule verwandt sind, nicht wirklich miteinander. –