2017-03-03 6 views
0

Ich habe 2 Tabellen, Car_Table und History_Table. Ich möchte in der Lage sein, den letzten Geschichtspunkt für alle Autos auszuwählen, wenn ihr Status auf "kaputt" gesetzt ist.So wählen Sie den letzten Datensatz nach Datum in einer verbundenen Tabelle

Die Tabellen sind wie folgt

Car_Table 
Car_ID Driver_Name Car_Status 
1  Alan  Broken 
2  Dave  Broken 

und

History_Table 
id Date  Notes  Car_Id 
1 01-01-2017 Change oil  1 
2 02-01-2017 Check Brakes 1 
3 02-01-2017 Service   2 
3 03-01-2017 Cleaning  2 

Als ich

tun
select Car_Table.Driver_Name,History_Table.Notes from Car_Table 
inner join History_Table on Car_Table.Car_ID = History_Table.CarID 
where Car_Table.Car_Status = 'Broken' 

ich alle die Geschichte Datensätze zurückgegeben. Gibt es eine Möglichkeit, das letzte Geschichtsobjekt für jedes Auto zu erhalten, das den Status "kaputt" hat?

Antwort

4

Sie finden für jedes Auto mit max Datum Zeile die left join Technik und dann kommen sie mit dem Car_table:

select Car_Table.Driver_Name, 
    History_Table.Notes 
from Car_Table 
inner join (
    select h1.* 
    from History_Table h1 
    left join History_Table h2 on h1.Car_ID = h2.Car_ID 
     and h1.date < h2.date 
    where h2.Car_ID is null 
    ) History_Table on Car_Table.Car_ID = History_Table.CarID 
where Car_Table.Car_Status = 'Broken'; 

Siehe offizielle MySQL-Website für alternative Lösungen (Aggregation in korrelierte und unkorrelierte Unterabfrage, die sind wahrscheinlich langsamer als die obige Lösung).

+1

Beachten Sie, dass diese Lösung schlecht skaliert – Strawberry

+0

@Strawberry - Ich habe einen Link zu Beispiel hinzugefügt, die die anderen beiden Alternativen der Lösung auch. – GurV

+0

Langsamer? Kaum! – Strawberry

1

können Sie eine Unterabfrage verwenden letzte Datensatz zu erhalten. Idealerweise sollte ein Index für das Feld 'Datum' vorhanden sein, wenn die Datensätze eine große Anzahl aufweisen.

 
select Car_Table.Driver_Name,History_Table.Notes 
    from Car_Table 
    inner join History_Table on Car_Table.Car_ID = History_Table.CarID 
    and History_Table.id=(
     select History_Table2.id 
     from History_Table2 
     Where History_Table2.CarID=History_Table.CarID 
     Order by date desc 
     Limit 1 
    ) 
    where Car_Table.Car_Status = 'Broken' 
1

Der effizienteste Weg, solche Berichte eine zusätzliche Spalte last_history_id im Car_Table schaffen würde bekommen sein. Jedes Mal, wenn ein Datensatz in History_Table eingefügt wird, würde ein Trigger die Spalte last_history_id in Car_Table aktualisieren. Es würde die Lese-Latenz für die Auswahl der gewünschten Datensätze verringern, aber in gewisser Weise könnte es ein Trick sein, wenn viele Aktualisierungen gleichzeitig durchgeführt würden.

Verwandte Themen