2017-01-13 4 views
0

Ich habe mir die meisten anderen Lösungen hier angesehen, aber keiner von ihnen scheint für mich zu arbeiten. Ich habe eine Tabelle mit ungefähr 100K Reihen darin.Laravel 5.3 - Reihenfolge der Ergebnisse über WhereIn Mysql

Jede Zeile ist ein Datensatz von einem Iot-Gerät, das die eindeutige ID dieses Geräts enthält. Die Geräte-ID kann 10K-Zeilen von 100K haben.

Reading::whereIn('device_id', $ids)->orderBy('created_at', 
'DESC')->groupBy('device_id')->get()-> 

Ich bin in der Lage, die IDs zu ziehen ich brauche und gruppieren sie zusammen mit „device_id“ als Abfrage oben aber sein das erste Ergebnis Kommissionierung und nicht die letzte für jeden ID.

Wie kann ich den neuesten Datensatz für jede ID anstelle der ältesten erhalten?

Ich habe Laravel Sammlungen und die umgekehrte(), erste(), neueste(); Option, aber ich kann es immer noch nicht bekommen

Irgendwelche Ideen?

UPDATE

Die best ich in der Lage gewesen, mit zu kommen ist diese Abfrage unter dem den letzten Datensatz für jeden

DEVICE_ID
SELECT t1.* FROM readings t1 WHERE t1.id = (SELECT t2.id FROM readings 
t2 WHERE t2.device_id = t1.device_id ORDER BY t2.id DESC LIMIT 1) 

nicht greift dann werde ich Schleife durch denjenigen Ergebnisse und greifen nur die Datensätze, auf die der Benutzer zugreifen kann.

Nicht schön, aber es funktioniert für jetzt.

Wenn jemand jemals weg findet es in eloquent zu tun bitte

Antwort

0

beantworten ich glaube, das sollte funktionieren?

Reading::select('device_id', 'id', DB::raw('MAX(created_at) AS latest'))->whereIn('device_id', $ids)->orderBy('latest', 'DESC')->groupBy('device_id')->get(); 

Hoffe, das hilft!

+0

ich diesen zu helfen „Error in Grammar.php Linie 58: strtolower() erwartet Parameter 1 sein Zeichenfolge mit dem angegebenen Objekt“ – ATechGuy

+0

Sie wahrscheinlich in dem übergebenen Instanz eines Objekts ... zeigen Sie uns den Code – GabMic

+0

welchen Code Eitan? mein Code ist oben, die $ IDs ist ein Array – ATechGuy

0

OK, ich glaube, dies funktionieren kann, wie frühere Versuche nicht tat:

$sub = Reading::orderBy('created_at','desc'); 

return DB::table(DB::raw("({$sub->toSql()}) as sub")) 
    ->whereIn('device_id', $ids) 
    ->groupBy('device_id') 
    ->get(); 

Sie im Grunde betreiben eine 'Sub-Abfrage'. Rufen Sie die Ergebnisse in der von Ihnen benötigten Reihenfolge ab und führen Sie dann die zweite Abfrage aus, um sie zu gruppieren.

+0

vorsichtig sein kannst. abhängig von der Speicher-Engine und den Indizes die Reihenfolge kann weg sein – nkconnor

0

Das ist eine ziemlich knifflige Frage, über die man nachdenken sollte. Sobald Sie die Frage im Datenbank-Jargon neu formuliert haben, etwa wie "Max-Record für jede ID in der MySQL-Abfrage", ist es ziemlich einfach, eine Menge von SO-Antworten zu finden.

Hier ist ein hoch bewertetes Beispiel auf SO: Retrieving the last record in each group

In Ihrer aktualisierten Abfrage, die Unterabfrage tatsächlich für jede Zeile neu berechnet wird, denke ich. Wir können besser durch Lesungen selbst Beitritt (überprüft Link oben als Referenz)

SELECT r1.* 
FROM readings r1 
    LEFT JOIN readings r2 
    ON r2.device_id = r1.device_id 
     AND r1.date_created < r2.date_created 
WHERE r2.device_id IS NULL # there is no row with a date_created greater than r1's 
; 

Indizes auf device_id und date_created ist ein einfacher erster Schritt für die Herstellung dieses schnellen

+0

auch daran erinnern, Sie können eine weitere where-Klausel hinzufügen, 'AND r2.device_id IN ($ ids)', und wenn sie numerisch sind, 'r2.device_id> ($ lowest_id) AND r2.device_id <($ highest_id) '. Dies ist wahrscheinlich besser als das Durchlaufen der Ergebnisse im Code. – nkconnor

0

ich es endlich in der Lage war zu aussortiert . Die folgende Abfrage gibt genau das zurück, was ich in Laravel möchte.

$sql = Reading::select('created_at', 'column1', 'column2', 'column3', 'column4', 'column5', 
'column6')->whereIn('device_id', ['0','0'])->toSql(); 

// 0 is just "empty" value, it doesn't matter here yet 

$db = DB::connection()->getPdo(); 
$query = $db->prepare($sql); 

// real ids im looking for 

$query->execute(array('ffvr5g6h', 'ccvl5f4rty')); 


$collection = collect($query); 

// change this to take ever (n) record 

//$collection = $collection->every(100); 
$collection = $collection->groupBy('device_id'); 

foreach ($collection as $collect) { 
       // process data 
       $end = $collect->last(); 
       print_r($end); 
      } 

oberhalb dieser Abfrage 100K Reihen in etwa einer halben Sekunde wird die Abfrage, so dass in einer Sammlung für Laravel, einmal in einer Sammlung i Gruppe von ID drehen, greifen dann die letzte Aufzeichnung von diesem Ergebnis.

Vielen Dank an alle diejenigen, die versuchten :)

Verwandte Themen