Ich habe einen Tabellenkunden, der eine Kunden-ID, eine E-Mail und eine Referenz speichert. Es gibt eine zusätzliche Tabelle customer_data, in der ein historischer Datensatz der am Kunden vorgenommenen Änderungen gespeichert ist. Wenn also eine Änderung vorgenommen wird, wird eine neue Zeile eingefügt.
Um die Kundeninformationen in einer Tabelle anzuzeigen, müssen die beiden Tabellen verknüpft werden. Es sollte jedoch nur die letzte Zeile aus customer_data mit der Kundentabelle verknüpft werden.
Es wird etwas komplizierter, da die Abfrage paginiert ist, also ein Limit und einen Offset hat.
Wie kann ich das mit MySQL machen? Ich glaube, ich möchte irgendwo einen DISTINCT einbauen ...
Die Abfrage im Moment ist wie folgt:
SELECT *, CONCAT(title,' ',forename,' ',surname) AS name
FROM customer c
INNER JOIN customer_data d on c.customer_id=d.customer_id
WHERE name LIKE '%Smith%' LIMIT 10, 20
Habe ich auch Recht, wenn ich denke, dass ich CONCAT mit LIKE auf diese Weise verwenden kann?
(Ich weiß zu schätzen, dass INNER JOIN möglicherweise die falsche Art von JOIN ist. Ich habe eigentlich keine Ahnung, was der Unterschied zwischen den verschiedenen JOINs ist. Ich werde das jetzt untersuchen!)
Antworten:
Möglicherweise möchten Sie Folgendes ausprobieren:
Beachten Sie, dass a
JOIN
nur ein Synonym für istINNER JOIN
.Testfall:
Ergebnis (Abfrage ohne
LIMIT
undWHERE
):quelle
Wenn Sie mit umfangreichen Abfragen arbeiten, verschieben Sie die Anforderung für die neueste Zeile besser in die where-Klausel. Es ist viel schneller und sieht sauberer aus.
quelle
sql_no_cache set
), während die Suche im Join mehrere Sekunden dauerte. Immer noch verblüfft, aber ich meine, mit solchen Ergebnissen kann man nicht streiten.Unter der Annahme, dass die Autoincrement-Spalte in
customer_data
benannt istId
, können Sie Folgendes tun:quelle
Für alle, die mit einer älteren Version von MySQL (vor 5.0 ish) arbeiten müssen, können Sie keine Unterabfragen für diesen Abfragetyp durchführen. Hier ist die Lösung, die ich machen konnte und die anscheinend großartig funktionierte.
Im Wesentlichen wird dabei die maximale ID Ihrer Datentabelle ermittelt, die mit dem Kunden verknüpft ist, und anschließend die Datentabelle mit der gefundenen maximalen ID verknüpft. Der Grund dafür ist, dass die Auswahl des Maximums einer Gruppe nicht garantiert, dass der Rest der Daten mit der ID übereinstimmt, es sei denn, Sie verbinden sie wieder mit sich selbst.
Ich habe dies nicht auf neueren Versionen von MySQL getestet, aber es funktioniert unter 4.0.30.
quelle
EXPLAIN
dass dies eine temporäre Tabelle und einen Dateisort verwendet. Durch HinzufügenORDER BY NULL
am Ende wird der Dateisort entfernt.SELECT *, MAX(firstData.id), MAX(secondData.id) [...]
. Durch den Wechsel zu konnteSELECT main.*, firstData2.*, secondData2.*, MAX(firstData.id), MAX(secondData.id), [...]
ich es logischerweise deutlich schneller machen. Auf diese Weise können die ersten Joins nur aus dem Index lesen, anstatt auch alle Daten aus dem Primärindex lesen zu müssen. Jetzt dauert die hübsche Lösung nur noch 1,9-mal so lange wie die auf Unterabfragen basierende Lösung.Ich weiß, dass diese Frage alt ist, aber sie hat im Laufe der Jahre viel Aufmerksamkeit erhalten, und ich denke, es fehlt ein Konzept, das jemandem in einem ähnlichen Fall helfen könnte. Der Vollständigkeit halber füge ich es hier hinzu.
Wenn Sie Ihr ursprüngliches Datenbankschema nicht ändern können, wurden viele gute Antworten gegeben, um das Problem einwandfrei zu lösen.
Wenn Sie können jedoch Ihr Schema ändern, würde ich raten , ein Feld in Ihrem hinzuzufügen
customer
Tabelle , die das hältid
der neuestencustomer_data
Rekord für diesen Kunden:Kunden abfragen
Das Abfragen ist so einfach und schnell wie möglich:
Der Nachteil ist die zusätzliche Komplexität beim Erstellen oder Aktualisieren eines Kunden.
Kunden aktualisieren
Wenn Sie einen Kunden aktualisieren möchten, fügen Sie einen neuen Datensatz in die
customer_data
Tabelle ein und aktualisieren dencustomer
Datensatz.Kunden erstellen
Beim Erstellen eines Kunden müssen Sie lediglich den
customer
Eintrag einfügen und dann dieselben Anweisungen ausführen:Einpacken
Die zusätzliche Komplexität beim Erstellen / Aktualisieren eines Kunden mag furchterregend sein, kann jedoch leicht mit Triggern automatisiert werden.
Wenn Sie ein ORM verwenden, kann dies sehr einfach zu verwalten sein. Das ORM kann sich darum kümmern, die Werte einzufügen, die IDs zu aktualisieren und die beiden Tabellen automatisch für Sie zu verbinden.
So
Customer
würde Ihr veränderliches Modell aussehen:Und Ihr unveränderliches
CustomerData
Modell, das nur Getter enthält:quelle
Ich denke, Sie müssen c.customer_id in c.id ändern
sonst Tabellenstruktur aktualisieren
quelle
Sie können dies auch tun
quelle
Es ist eine gute Idee, die tatsächlichen Daten in der Tabelle " customer_data " zu protokollieren . Mit diesen Daten können Sie alle Daten aus der Tabelle "customer_data" auswählen, wie Sie möchten.
quelle