SQL-Verknüpfung: Auswählen der letzten Datensätze in einer Eins-zu-viele-Beziehung
Angenommen ich habe eine Tabelle Kunden und eine Tabelle der Einkäufe. Jedem Kauf gehört einem Kunden. Ich möchte eine Liste aller Kunden, die zusammen mit Ihren letzten Einkauf in einer SELECT-Anweisung. Was ist die beste Praxis? Jede Beratung über die Erstellung von Indizes?
Bitte verwenden Sie diese Tabelle/Spaltennamen in Ihrer Antwort:
- Kunde: id, name
- kaufen: id, kunden_id, item_id, Datum
Und in komplizierteren Situationen, wäre es (performance-wise) positiv auf denormalize der Datenbank, indem Sie den letzten Kauf in die customer-Tabelle?
Wenn die (Kauf -) id ist garantiert nach Datum sortiert, können die Aussagen vereinfacht werden, indem Sie mit so etwas wie LIMIT 1
?
InformationsquelleAutor der Frage netvope | 2010-01-21
Du musst angemeldet sein, um einen Kommentar abzugeben.
Dies ist ein Beispiel für die
greatest-n-per-group
problem, das erschien regelmäßig auf StackOverflow.Hier ist, wie ich in der Regel empfehlen die Lösung:
Erklärung: gegeben eine Reihe
p1
sollte es keine Zeilep2
mit den gleichen Kunden und zu einem späteren Zeitpunkt (oder in dem Fall von Bindungen, die späterid
). Wenn wir finden, dass, um wahr zu sein, dannp1
ist der jüngste Kauf für die Kunden.Bezüglich der Indizes, ich würde erstellen Sie einen zusammengesetzten index in
purchase
über die Spalten (customer_id
date
id
). Das kann erlauben, wird das outer-join zu tun mit einem abdeckenden index. Werden Sie sicher, dass der test auf Ihrer Plattform, denn Optimierung ist von der Implementierung abhängig. Verwenden Sie die Funktionen Ihres RDBMS zu analysieren, um die Optimierung zu planen. E. g.EXPLAIN
auf MySQL.Einige Leute verwenden Unterabfragen anstelle der Lösung, die ich oben zeige, aber ich finde meine Lösung macht es einfacher zu lösen Bindungen.
InformationsquelleAutor der Antwort Bill Karwin
Könnte man auch versuchen, dies zu tun mit einem sub-select
Den wählen, sollte sich auf alle Kunden und Ihre Letzten Kaufdatum.
InformationsquelleAutor der Antwort Adriaan Stander
Du noch nicht angegeben, der Datenbank. Wenn es eine, die analytischen Funktionen kann es schneller sein, um diesen Ansatz verwenden, als die GRUPPE DURCH eine(auf jeden Fall schneller in Oracle, wahrscheinlich schneller in die späten Editionen von SQL Server, weiß nicht, über andere).
Syntax in SQL Server wäre:
InformationsquelleAutor der Antwort Madalina Dragomir
Ein weiterer Ansatz wäre die Verwendung einer
NOT EXISTS
Bedingung in den join-Bedingung zu testen, für spätere Käufe:InformationsquelleAutor der Antwort Stefan Haberl
Fand ich diesen thread als Lösung für mein problem.
Aber wenn ich habe versucht, Ihnen die Leistung zu gering war. Balg ist mein Vorschlag für eine bessere Leistung.
Hoffe, dass dies hilfreich sein wird.
InformationsquelleAutor der Antwort Mathee
Getestet auf SQLite:
Den
max()
Aggregat-Funktion stellen Sie sicher, dass die aktuellen Kauf ausgewählt ist aus jeder Gruppe (geht aber davon aus, dass die Datum-Spalte in einem format, wobei max() gibt das aktuelle - was der Normalfall ist). Wenn Sie damit umgehen wollen Einkäufe mit dem gleichen Datum, dann können Siemax(p.date, p.id)
.In Bezug auf die Indizes, würde ich einen index auf kaufen mit (customer_id, Datum, [jedem anderen Kauf Spalten, die Sie wollen zurück in Ihre select]).
Den
LEFT OUTER JOIN
(im Gegensatz zuINNER JOIN
) stellen Sie sicher, dass die Kunden, die noch nie einen Kauf getätigt haben, sind ebenfalls enthalten.InformationsquelleAutor der Antwort Mark
Bitte versuchen Sie dieses,
InformationsquelleAutor der Antwort Milad Shahbazi
Versuchen Sie dies, Es wird helfen.
Ich habe diese in mein Projekt.
InformationsquelleAutor der Antwort Rahul Murari
Wenn Sie mit PostgreSQL können Sie
DISTINCT ON
zu finden, die erste Zeile in einer Gruppe.PostgreSQL-Docs - Verschiedene Auf
Beachten Sie, dass die
DISTINCT ON
field(s) -- hiercustomer_id
-- muss mit der am weitesten Links Feld(s) in derORDER BY
- Klausel.Achtung: Dies ist ein nicht dem Standard entsprechende Klausel.
InformationsquelleAutor der Antwort Tate Thurston