2016-06-29 4 views
0

Ich versuche, den letzten WorkOrder für jeden Customer auszuwählen. Ich habe ORDER BY und GROUP BY verwendet, aber das zurückgegebene Ergebnis ist nicht das neueste WorkOrder.Begrenzen Sie eine Zeile pro eindeutigen Spaltenwert, indem Sie nach max. Spaltenwert wählen

Tabellenstruktur:

WorkOrder 
    id 
    customer_id 
    create_date 
    ... 

Beispieldaten:

WorkOrder.id WorkOrder.customer_id WorkOrder.create_date ... 
1    1      2012-01-01 12:00:00 
2    1      2016-06-29 12:00:00 
3    2      2015-05-05 12:00:00 

Gewünschtes Ergebnis:

WorkOrder.id WorkOrder.customer_id WorkOrder.create_date ... 
2    1      2016-06-29 12:00:00 
3    2      2015-05-05 12:00:00 

Aktuelle Code:

$query = DB::table('WorkOrder') 
    ->orderBy('WorkOrder.create_date', 'desc') 
    ->groupBy('WorkOrder.customer_id'); 

// select * from `WorkOrder` group by `WorkOrder`.`customer_id` order by `WorkOrder`.`create_date` desc 

Aktuell Ergebnis:

WorkOrder.id WorkOrder.customer_id WorkOrder.create_date ... 
1    1      2012-01-01 12:00:00 
3    2      2015-05-05 12:00:00 
+0

Sie verwenden 'group by', was bedeutet, dass nicht gruppierte Felder in beliebiger Reihenfolge zurückgegeben werden können. mysql gibt im Allgemeinen den ersten gefundenen Wert zurück, auch wenn dieser nicht von derselben Zeile stammt, aus der die gruppierten Felder ihre Werte erhalten. –

+0

Also nix die 'Gruppe von'? Wie beschränke ich es auf ein Ergebnis pro 'customer_id'? – Shane

+0

kann es nicht als einzelne einfache Abfrage tun. Sie benötigen eine Unterabfrage, um die IDs der gewünschten Zeilen abzurufen, und anschließend eine äußere Abfrage, um die gesamte Zeile für diese IDs abzurufen. –

Antwort

1

Verwendung max Funktion

SELECT WorkOrder.id, WorkOrder.customer_id, MAX(WorkOrder.create_date) FROM `WorkOrder` GROUP BY `WorkOrder`.`customer_id` ORDER BY `WorkOrder`.`create_date` DESC 
+0

Wie funktioniert das überhaupt? GROUP BY entspricht nicht dem SELECT. – Grayson

+0

Es wird nach Ergebnis nach Kundennummer gruppiert und gibt den maximal erstellten Datumswert –

+0

Was passiert mit der WorkOrder.id? In ANSI SQL sollte dies einen Fehler erzeugen. – Grayson

1

Try this:

SELECT * FROM WorkOrder 
WHERE (customer_id, create_date) IN 
     (SELECT customer_id, MAX(create_date) FROM WorkOrder 
     GROUP By customer_id) 
ORDER BY ... 
+0

@Shane hast du das schon getestet? – Grayson

+0

Die Abfrage dauerte einige Minuten. Mahesh ist praktisch sofort. – Shane

+0

@Shane gibt es einen Index für customer_id? – Grayson

1

Ich neige dazu, dies mit einer korrelierten Unterabfrage zu tun:

select wo.* 
from workorder wo 
where create_date = (select max(wo2.create_date) 
        from workorder wo2 
        where wo2.customer_id = wo.customer_id 
        ); 

Dieser Vorteil dieses Ansatzes über eine group by in der Unterabfrage:

  • Wenn Sie in der where Klausel andere Filter haben, dann ist dieser Wille Sehen Sie nur die Werte in einer reduzierten Reihe von Zeilen nach.
  • Es kann einen Index für die Suche verwenden, ohne zuerst eine Aggregation durchführen zu müssen.
+0

Können Sie ein Szenario erstellen, in dem es schneller als die entsprechende unkorrelierte Version ausgeführt wird? Bei meinen Tests hat es das nie gegeben. – Strawberry

+1

Diese Abfrage benötigt eine beträchtliche Zeit im Vergleich zu Mahesh. Ich werde ein paar Tests mit meinen anderen 'WHERE'-Klauseln machen, um zu sehen, ob sie am Ende stehen. – Shane

+0

@Shane Er verarbeitet jede Zeile in der Tabelle und führt die Unterabfrage für jede Zeile aus. Das wird langsam. – Grayson

Verwandte Themen