Ich habe einen Tischkunden, der eine customer_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 wird, d. H. Wenn eine Änderung vorgenommen wurde, 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 verbunden werden.
Es wird etwas komplizierter, da die Abfrage paginiert ist, also ein Limit und ein Offset hat.
Wie kann ich das mit MySQL machen? Ich glaube, ich möchte irgendwo ein DISTINCT einsetzen ...
Die Abfrage auf die Minute 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
Bin ich außerdem der Meinung, dass ich CONCAT mit LIKE auf diese Weise verwenden kann?
(Ich schätze, dass INNER JOIN die falsche Art von JOIN ist. Ich habe keine Ahnung, was der Unterschied zwischen den verschiedenen JOINs ist. Ich werde das jetzt untersuchen!)
Möglicherweise möchten Sie Folgendes versuchen:
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
JOIN (
SELECT MAX(id) max_id, customer_id
FROM customer_data
GROUP BY customer_id
) c_max ON (c_max.customer_id = c.customer_id)
JOIN customer_data cd ON (cd.id = c_max.max_id)
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
LIMIT 10, 20;
Beachten Sie, dass eine JOIN
nur ein Synonym für INNER JOIN
ist.
Testfall:
CREATE TABLE customer (customer_id int);
CREATE TABLE customer_data (
id int,
customer_id int,
title varchar(10),
forename varchar(10),
surname varchar(10)
);
INSERT INTO customer VALUES (1);
INSERT INTO customer VALUES (2);
INSERT INTO customer VALUES (3);
INSERT INTO customer_data VALUES (1, 1, 'Mr', 'Bobby', 'Smith');
INSERT INTO customer_data VALUES (2, 1, 'Mr', 'Bob', 'Smith');
INSERT INTO customer_data VALUES (3, 2, 'Mr', 'Jane', 'Green');
INSERT INTO customer_data VALUES (4, 2, 'Miss', 'Jane', 'Green');
INSERT INTO customer_data VALUES (5, 3, 'Dr', 'Jack', 'Black');
Ergebnis (Abfrage ohne LIMIT
und WHERE
):
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
JOIN (
SELECT MAX(id) max_id, customer_id
FROM customer_data
GROUP BY customer_id
) c_max ON (c_max.customer_id = c.customer_id)
JOIN customer_data cd ON (cd.id = c_max.max_id);
+-----------------+
| name |
+-----------------+
| Mr Bob Smith |
| Miss Jane Green |
| Dr Jack Black |
+-----------------+
3 rows in set (0.00 sec)
Wenn Sie mit umfangreichen Abfragen arbeiten, verschieben Sie die Anforderung für die letzte Zeile in der where-Klausel. Es ist viel schneller und sieht sauberer aus.
SELECT c.*,
FROM client AS c
LEFT JOIN client_calling_history AS cch ON cch.client_id = c.client_id
WHERE
cch.cchid = (
SELECT MAX(cchid)
FROM client_calling_history
WHERE client_id = c.client_id AND cal_event_id = c.cal_event_id
)
Unter der Annahme, dass die Autoincrement-Spalte in customer_data
den Namen Id
hat, können Sie Folgendes tun:
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%'
AND d.ID = (
Select Max(D2.Id)
From customer_data As D2
Where D2.customer_id = D.customer_id
)
LIMIT 10, 20
Für jeden, der mit einer älteren Version von MySQL (vor Version 5.0 ish) arbeiten muss, können Sie für diesen Abfragetyp keine Unterabfragen ausführen. Hier ist die Lösung, die ich konnte, und es schien großartig zu funktionieren.
SELECT MAX(d.id), d2.*, CONCAT(title,' ',forename,' ',surname) AS name
FROM customer AS c
LEFT JOIN customer_data as d ON c.customer_id=d.customer_id
LEFT JOIN customer_data as d2 ON d.id=d2.id
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
GROUP BY c.customer_id LIMIT 10, 20;
Im Wesentlichen ist dies die Ermittlung der maximalen ID Ihrer Datentabelle, die sie mit dem Kunden verbindet, und dann die Datentabelle mit der gefundenen maximalen ID. Der Grund dafür ist, dass die Auswahl des Maximums einer Gruppe nicht garantiert, dass die restlichen Daten mit der ID übereinstimmen, es sei denn, Sie fügen sie wieder zusammen.
Ich habe dies nicht mit neueren Versionen von MySQL getestet, aber es funktioniert mit 4.0.30.
Ich weiß, dass diese Frage alt ist, aber sie hat im Laufe der Jahre viel Aufmerksamkeit auf sich gezogen und ich denke, es fehlt ein Konzept, das jemandem in einem ähnlichen Fall helfen könnte. Ich füge es hier der Vollständigkeit halber hinzu.
Wenn Sie Ihr ursprüngliches Datenbankschema nicht ändern können, wurden viele gute Antworten bereitgestellt, die das Problem gut lösen.
Wenn Sie jedoch can Ihr Schema ändern, würde ich empfehlen, ein Feld in Ihrer customer
-Tabelle hinzuzufügen, das die id
des neuesten customer_data
-Datensatzes für diesen Kunden enthält:
CREATE TABLE customer (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
current_data_id INT UNSIGNED NULL DEFAULT NULL
);
CREATE TABLE customer_data (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
customer_id INT UNSIGNED NOT NULL,
title VARCHAR(10) NOT NULL,
forename VARCHAR(10) NOT NULL,
surname VARCHAR(10) NOT NULL
);
Das Abfragen ist so einfach und schnell wie möglich:
SELECT c.*, d.title, d.forename, d.surname
FROM customer c
INNER JOIN customer_data d on d.id = c.current_data_id
WHERE ...;
Der Nachteil ist die zusätzliche Komplexität beim Erstellen oder Aktualisieren eines Kunden.
Wenn Sie einen Kunden aktualisieren möchten, fügen Sie einen neuen Datensatz in die Tabelle customer_data
ein und aktualisieren den Datensatz customer
.
INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(2, 'Mr', 'John', 'Smith');
UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = 2;
Beim Erstellen eines Kunden müssen Sie lediglich den Eintrag customer
einfügen und dann die gleichen Anweisungen ausführen:
INSERT INTO customer () VALUES ();
SET @customer_id = LAST_INSERT_ID();
INSERT INTO customer_data (customer_id, title, forename, surname) VALUES(@customer_id, 'Mr', 'John', 'Smith');
UPDATE customer SET current_data_id = LAST_INSERT_ID() WHERE id = @customer_id;
Die zusätzliche Komplexität für das Erstellen/Aktualisieren eines Kunden ist möglicherweise furchterregend, kann jedoch leicht mit Triggern automatisiert werden.
Wenn Sie ein ORM verwenden, kann dies sehr einfach zu verwalten sein. Der ORM kann für das Einfügen der Werte, das Aktualisieren der IDs und das automatische Verknüpfen der beiden Tabellen sorgen.
So würde Ihr veränderliches Customer
-Modell aussehen:
class Customer
{
private int id;
private CustomerData currentData;
public Customer(String title, String forename, String surname)
{
this.update(title, forename, surname);
}
public void update(String title, String forename, String surname)
{
this.currentData = new CustomerData(this, title, forename, surname);
}
public String getTitle()
{
return this.currentData.getTitle();
}
public String getForename()
{
return this.currentData.getForename();
}
public String getSurname()
{
return this.currentData.getSurname();
}
}
Und Ihr unveränderliches CustomerData
-Modell, das nur Getter enthält:
class CustomerData
{
private int id;
private Customer customer;
private String title;
private String forename;
private String surname;
public CustomerData(Customer customer, String title, String forename, String surname)
{
this.customer = customer;
this.title = title;
this.forename = forename;
this.surname = surname;
}
public String getTitle()
{
return this.title;
}
public String getForename()
{
return this.forename;
}
public String getSurname()
{
return this.surname;
}
}
SELECT CONCAT(title,' ',forename,' ',surname) AS name * FROM customer c
INNER JOIN customer_data d on c.id=d.customer_id WHERE name LIKE '%Smith%'
ich denke, Sie müssen c.customer_id in c.id ändern
sonst aktualisieren Sie die Tabellenstruktur
Sie können das auch tun
SELECT CONCAT(title, ' ', forename, ' ', surname) AS name
FROM customer c
LEFT JOIN (
SELECT * FROM customer_data ORDER BY id DESC
) customer_data ON (customer_data.customer_id = c.customer_id)
GROUP BY c.customer_id
WHERE CONCAT(title, ' ', forename, ' ', surname) LIKE '%Smith%'
LIMIT 10, 20;
Es ist eine gute Idee, die tatsächlichen Daten in der Tabelle " customer_data " zu protokollieren. Mit diesen Daten können Sie nach Belieben alle Daten aus der Tabelle "customer_data" auswählen.
Das könnte helfen
So wählen Sie den neuesten Satz datierter Datensätze aus einer MySQL-Tabelle aus
Sie können eine Unterabfrage verwenden, um die neuesten Datensätze abzurufen und sich dann Ihrem Kunden anzuschließen.