2016-07-20 17 views
0

Ich arbeite an einem Produktbeispiel Inventarsystem, wo ich die Bewegung der Produkte verfolgen. Der Status jedes Produkts kann den Status "IN" oder "OUT" oder "REMOVED" haben. Jede Zeile der Tabelle repräsentiert einen neuen Eintrag, wobei ID, Status und Datum eindeutig sind. Jedes Produkt hat auch eine Seriennummer.Wählen Sie die aktuellsten Datensätze aus mehreren identischen Zeilen in der MySQL-Datenbank

Ich brauche Hilfe mit einer SQL-Abfrage, die alle Produkte zurückgibt, die derzeit "OUT" sind. Wenn ich einfach nur SELECT * FROM table WHERE status = "IN" wähle, werden alle Produkte zurückgegeben, die jemals den Status IN hatten.

Jedes Mal, wenn das Produkt ein- und ausgeht, dupliziere ich die letzte Zeile des betreffenden Produkts, ändere den Status und aktualisiere das Datum und es wird automatisch eine neue ID erhalten. Hier

ist die Tabelle, die ich habe:

id | serial_number | product | color | date  | status 
------------------------------------------------------------ 
1 | K0T4N   | XYZ  | silver | 2016-07-01 | IN 
2 | X56Z7   | ABC  | silver | 2016-07-01 | IN 
3 | 96T4F   | PQR  | silver | 2016-07-01 | IN 
4 | K0T4N   | XYZ  | silver | 2016-07-02 | OUT 
5 | 96T4F   | PQR  | silver | 2016-07-03 | OUT 
6 | F0P22   | DEF  | silver | 2016-07-04 | OUT 
7 | X56Z7   | ABC  | silver | 2016-07-05 | OUT 
8 | F0P22   | DEF  | silver | 2016-07-06 | IN 
9 | K0T4N   | XYZ  | silver | 2016-07-07 | IN 
10 | X56Z7   | ABC  | silver | 2016-07-08 | IN 
11 | X56Z7   | ABC  | silver | 2016-07-09 | REMOVED 
12 | K0T4N   | XYZ  | silver | 2016-07-10 | OUT 
13 | 96T4F   | PQR  | silver | 2016-07-11 | IN 
14 | F0P22   | DEF  | silver | 2016-07-12 | OUT 

Antwort

1

Diese Abfrage wird Ihnen alle aktuellen Datensätze für jede serial_number

SELECT a.* FROM your_table a 
LEFT JOIN your_table b ON a.serial_number = b.serial_number AND a.id < b.id 
WHERE b.serial_number IS NULL 

Unten Abfrage wird Ihre erwartete Ergebnis

SELECT a.* FROM your_table a 
LEFT JOIN your_table b ON a.serial_number = b.serial_number AND a.id < b.id 
WHERE b.serial_number IS NULL AND a.status LIKE 'OUT' 
geben
+0

Jeder Erfolg Bro? –

+0

danke, arbeitete wie ein Charme :) –

+0

Das ist großartig. Können Sie bitte upvote und akzeptieren meine Antwort;) –

1

Es gibt zwei gute Möglichkeiten, dies zu tun. Welcher Weg in Bezug auf die Leistung am besten ist, hängt von verschiedenen Faktoren ab. Versuchen Sie beides.

SELECT 
t1.* 
FROM table t 
LEFT OUTER JOIN table later_t 
ON later_t.serial_number = t.serial_number 
AND later_t.date > t.date 
WHERE later_t.id IS NULL 
AND t.status = "OUT" 

welche Spalte Sie von later_t für IS NULL überprüfen spielt keine Rolle, solange die Spalte NOT NULL in der Tabellendefinition deklariert wird.

Die andere logisch äquivalente Methode ist:

SELECT 
t.* 
FROM table t 
INNER JOIN (
SELECT 
serial_number, 
MAX(date) AS date 
FROM table 
GROUP BY serial_number 
) latest_t 
ON later_t.serial_number = t.serial_number 
AND latest_t.date = t.date 
WHERE t.status = "OUT" 

Für jede dieser Anfragen, ich stark den folgenden Index vorschlagen:

ALTER TABLE table 
ADD INDEX `LatestSerialStatus` (serial_number,date) 

Ich benutze diese Art der Abfrage eine Menge in meiner eigenen Arbeit und den obigen Index als Primärschlüssel für Tabellen verwenden. Die Abfrageleistung ist in solchen Fällen für diese Art von Abfragen extrem schnell.

Siehe auch die documentation für diesen Abfragetyp.

+0

danke für die Lösung, und ich danke Ihnen für den Rat über die Indizierung, begann ich es und alles funktioniert jetzt perfekt –